Discussion:
[SDL] Uneven V-sync
Edition Chamäleon
2017-01-16 15:17:14 UTC
Permalink
Hi there,

I've got an issue with v-sync on android. My Game is running perfectly on my pc and my laptop on Windows with 60 frames per sec. All scrolling and moving is perfectly smooth, even if there are lots of sprites on the screen. But on Android I've got problems with a strongly fluctuating framerate. It varies from 18 fps to 45 fps. Even if I do no scrolling and almost no rendercopy. Playing the game, fps can take any number ( 22, 27, 33, 37, 39, 44, 45 ), means there is no common divisor. Looks like VSYNC isn't working at all, or background processes on my android device disturb the flow massively. [Shocked]

Settings:
using SDL 2.0.3
my game is in c++
Testdevices : Samsung S4 mini , Samsung S3 mini, Samsung Tab A6, Asus Nexus7, Trekstore Suftab 9.6 ( Testdevices reach from old to new and from weak to powerful, but all show the problem, seems it is not dependent on the processor speed )
SDL_RENDERER_ACCELERATED is on
SDL_RENDERER_PRESENTVSYNC is on
SDL_THREAD_PRIORITY_HIGH is set
developing with 960 x 540 Pixel
Background processes are dissabled in the developer options on the samsung device

Any ideas how this can be fixed ?

Thanks in advance,

Michael
rtrussell
2017-01-16 22:30:10 UTC
Permalink
Post by Edition Chamäleon
Playing the game, fps can take any number ( 22, 27, 33, 37, 39, 44, 45 ), means there is no common divisor. Looks like VSYNC isn't working at all
My experience is that SDL_RENDERER_PRESENTVSYNC works as expected on Android. On four separate devices (like yours, with a wide range of performances) doing little else but waiting in SDL_RenderPresent() results in a constant frame rate very close to 60.0 fps. However I am using GLES 1, not GLES 2, and I don't know whether that makes a difference.

Richard.
Triang3l
2017-01-17 13:06:37 UTC
Permalink
Most likely you just have too low framerate in your game, it's way below
60. Maybe you're doing something fundamentally wrong like calling
glDrawElements/glDrawArrays for each sprite or uploading textures every
frame. Also on Android, there are very few GPU drivers that DON'T let
you disable vsync (but, for example, on Adreno only occasionally up to
70-80) without specific system development options, so vsync is a rule,
not an exception, there shouldn't be anything broken with it.
Post by Edition Chamäleon
Playing the game, fps can take any number ( 22, 27, 33, 37, 39, 44, 45
), means there is no common divisor. Looks like VSYNC isn't working at
all
My experience is that SDL_RENDERER_PRESENTVSYNC works as expected on
Android. On four separate devices (like yours, with a wide range of
performances) doing little else but waiting in SDL_RenderPresent()
results in a constant frame rate very close to 60.0 fps. However I am
using GLES 1, not GLES 2, and I don't know whether that makes a
difference.
Richard.
_______________________________________________
SDL mailing list
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Edition Chamäleon
2017-01-18 12:40:23 UTC
Permalink
Maybe you're doing something fundamentally wrong like calling glDrawElements/glDrawArrays for each sprite or uploading textures every frame
Hi,

I didn't use any of this functions. I used SDL_RenderCopy and SDL_RenderCopyEx for the drawing. Further SDL_SetTextureColorMod, SDL_SetTextureAlphaMod, SDL_SetTextureBlendMode, SDL_SetRenderDrawColor, SDL_RenderClear, SDL_RenderPresent a.s.o. I think I did nothing extravagant. What do you mean with "uploading textures" ? IMG_Load or SDL_CreateTextureFromSurface or sth ? I don't load textures during the game.

About the functionality or v-sync : I would understand if I got a multiple of 16,67 ms as fps. ( 17, 33, 50, 83 ) . That would proof, that vsync works and that my gamecode uses to much time. But as I wrote I get lots of values between.
Doesn't that proof that v-sync isn't working, or what am I missing here ?

Thanx in advance,
Michael
rtrussell
2017-01-18 12:54:25 UTC
Permalink
I would understand if I got a multiple of 16,67 ms as fps. ( 17, 33, 50, 83 ) . That would proof, that vsync works and that my gamecode uses to much time. But as I wrote I get lots of values between. Doesn't that proof that v-sync isn't working, or what am I missing here ?
You quoted 'frames per second' figures, so I assumed they were an average measured over more than one frame; in that case you cannot expect to see specific values because the frames may not all be the same length. If in fact you are measuring the periods of individual frames then I agree you should expect to see multiples of 16.7 milliseconds.

Richard.
Edition Chamäleon
2017-01-18 13:11:25 UTC
Permalink
Hi ,

to make it more precise : I made another test with almost no sprite-action, no scrolling background no nothing just the player on the screen. Moving arround a bit the fps value changes. Standing still the fps is constant. But with lots of different values in between the multiple of 16,67m2 for one iteration.

I get following different results ( as fps and in millisecs for one single Iteration ) :

31 fps 32,26 ms
32 fps 31,25 ms
33 fps 30,30 ms
34 fps 29,41 ms
35 fps 28,57 ms
36 fps 27,78 ms
37 fps 27,03 ms
38 fps 26,32 ms
39 fps 25,64 ms
41 fps 24,39 ms
43 fps 23,26 ms
44 fps 22,73 ms
46 fps 21,74 ms
56 fps 17,86 ms
61 fps 16,39 ms


I assume that if v-sync would work I would get :

fps ms
60 fps 16,67 ms
30 fps 33,33 ms
20 fps 50,00 ms
15 fps 66,67 ms
12 fps 83,33 ms
10 fps 100,00 ms
9 fps 116,67 ms
8 fps 133,33 ms
7 fps 150,00 ms
6 fps 166,67 ms
5 fps 183,33 ms
5 fps 200,00 ms
5 fps 216,67 ms
4 fps 233,33 ms
4 fps 250,00 ms

Michael
Edition Chamäleon
2017-01-18 16:32:14 UTC
Permalink
Hi there,

I made another test with a minimal Programm (see code). It just sets up the renderer , checks if v-sync is on, and displays a simple grafic. I get iterations from 6 ms to 47 ms. ( see list ).
I think v-sync isn't working here. Am I wrong ?

Michael




Code:
JNIEXPORT void JNICALL Java_de_editionchamaeleon_ECApp_ECActivity_SendScreenSizeToNative ( JNIEnv* pEnv, jobject pThis, jint pX , jint pY )
{
screenW = pX;
screenH = pY;
};


int main(int argc, char* argv[])
{

SDL_Window* m_window = SDL_CreateWindow( "GE" , 0, 0, screenW, screenH, SDL_WINDOW_BORDERLESS | SDL_WINDOW_OPENGL );

SDL_Renderer* m_renderer = SDL_CreateRenderer( m_window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED );
SDL_SetRenderDrawColor(m_renderer, 0, 255, 0, 255);
SDL_Surface* surface = IMG_Load( "grafic/loadAnimation.png" );
SDL_Texture* rawTexture = SDL_CreateTextureFromSurface( m_renderer, surface );
SDL_Rect SDL_srcRect = { 0,0,0,0 };
SDL_QueryTexture( rawTexture, NULL, NULL, &SDL_srcRect.w, &SDL_srcRect.h );
SDL_Rect SDL_destRect = { 0,0,0,0 };
SDL_destRect.w = screenW;
SDL_destRect.h = screenH;


SDL_RendererInfo info;
SDL_GetRendererInfo( m_renderer, &info );
string text;

if ( info.flags & (0x01 << 3))
{
text = "Renderer is SDL_RENDERER_TARGETTEXTURE";
__android_log_print ( ANDROID_LOG_VERBOSE, "Mw", text.c_str() );
}

if ( info.flags & (0x01 << 2))
{
text = "Renderer is SDL_RENDERER_PRESENTVSYNC";
__android_log_print ( ANDROID_LOG_VERBOSE, "Mw", text.c_str() );
}

if ( info.flags & (0x01 << 1))
{
text = "Renderer is SDL_RENDERER_ACCELERATED";
__android_log_print ( ANDROID_LOG_VERBOSE, "Mw", text.c_str() );
}

if ( info.flags & (0x01 ))
{
text = "Renderer is SDL_RENDERER_SOFTWARE";
__android_log_print ( ANDROID_LOG_VERBOSE, "Mw", text.c_str() );
}


int time1, time2, time3;

while (1)
{
time1 = SDL_GetTicks();

SDL_RenderClear( m_renderer );
SDL_RenderCopy( m_renderer, rawTexture, &SDL_srcRect, &SDL_destRect );
SDL_RenderPresent( m_renderer );

time2 = SDL_GetTicks();
time3 = time2 - time1;

ostringstream sstream;
sstream << time3 << " ms";
text = sstream.str();
__android_log_print ( ANDROID_LOG_VERBOSE, "Mw", text.c_str() );
}


}






and a get this:




Code:
01-18 17:26:05.973: V/Mw:(8200): Sending Screensize : 960 , 540
01-18 17:26:06.373: V/Mw(8200): Renderer is SDL_RENDERER_TARGETTEXTURE
01-18 17:26:06.373: V/Mw(8200): Renderer is SDL_RENDERER_PRESENTVSYNC
01-18 17:26:06.373: V/Mw(8200): Renderer is SDL_RENDERER_ACCELERATED
01-18 17:26:06.393: V/Mw(8200): 20 ms
01-18 17:26:06.403: V/Mw(8200): 11 ms
01-18 17:26:06.413: V/Mw(8200): 7 ms
01-18 17:26:06.413: V/Mw(8200): 5 ms
01-18 17:26:06.433: V/Mw(8200): 16 ms
01-18 17:26:06.453: V/Mw(8200): 17 ms
01-18 17:26:06.463: V/Mw(8200): 16 ms
01-18 17:26:06.483: V/Mw(8200): 16 ms
01-18 17:26:06.493: V/Mw(8200): 16 ms
01-18 17:26:06.513: V/Mw(8200): 17 ms
01-18 17:26:06.533: V/Mw(8200): 16 ms
01-18 17:26:06.553: V/Mw(8200): 18 ms
01-18 17:26:06.573: V/Mw(8200): 21 ms
01-18 17:26:06.583: V/Mw(8200): 17 ms
01-18 17:26:06.604: V/Mw(8200): 11 ms
01-18 17:26:06.614: V/Mw(8200): 16 ms
01-18 17:26:06.634: V/Mw(8200): 17 ms
01-18 17:26:06.654: V/Mw(8200): 17 ms
01-18 17:26:06.664: V/Mw(8200): 19 ms
01-18 17:26:06.684: V/Mw(8200): 16 ms
01-18 17:26:06.704: V/Mw(8200): 16 ms
01-18 17:26:06.734: V/Mw(8200): 29 ms
01-18 17:26:06.744: V/Mw(8200): 17 ms
01-18 17:26:06.764: V/Mw(8200): 15 ms
01-18 17:26:06.784: V/Mw(8200): 18 ms
01-18 17:26:06.794: V/Mw(8200): 15 ms
01-18 17:26:06.814: V/Mw(8200): 21 ms
01-18 17:26:06.834: V/Mw(8200): 12 ms
01-18 17:26:06.844: V/Mw(8200): 18 ms
01-18 17:26:06.864: V/Mw(8200): 16 ms
01-18 17:26:06.884: V/Mw(8200): 19 ms
01-18 17:26:06.904: V/Mw(8200): 17 ms
01-18 17:26:06.914: V/Mw(8200): 15 ms
01-18 17:26:06.934: V/Mw(8200): 14 ms
01-18 17:26:06.944: V/Mw(8200): 17 ms
01-18 17:26:06.964: V/Mw(8200): 17 ms
01-18 17:26:06.984: V/Mw(8200): 17 ms
01-18 17:26:06.994: V/Mw(8200): 17 ms
01-18 17:26:07.014: V/Mw(8200): 21 ms
01-18 17:26:07.034: V/Mw(8200): 13 ms
01-18 17:26:07.044: V/Mw(8200): 16 ms
01-18 17:26:07.064: V/Mw(8200): 17 ms
01-18 17:26:07.084: V/Mw(8200): 16 ms
01-18 17:26:07.094: V/Mw(8200): 17 ms
01-18 17:26:07.114: V/Mw(8200): 18 ms
01-18 17:26:07.134: V/Mw(8200): 16 ms
01-18 17:26:07.144: V/Mw(8200): 17 ms
01-18 17:26:07.164: V/Mw(8200): 16 ms
01-18 17:26:07.184: V/Mw(8200): 16 ms
01-18 17:26:07.194: V/Mw(8200): 17 ms
01-18 17:26:07.214: V/Mw(8200): 17 ms
01-18 17:26:07.234: V/Mw(8200): 16 ms
01-18 17:26:07.244: V/Mw(8200): 16 ms
01-18 17:26:07.264: V/Mw(8200): 17 ms
01-18 17:26:07.284: V/Mw(8200): 16 ms
01-18 17:26:07.294: V/Mw(8200): 17 ms
01-18 17:26:07.314: V/Mw(8200): 17 ms
01-18 17:26:07.334: V/Mw(8200): 16 ms
01-18 17:26:07.344: V/Mw(8200): 17 ms
01-18 17:26:07.364: V/Mw(8200): 17 ms
01-18 17:26:07.384: V/Mw(8200): 16 ms
01-18 17:26:07.394: V/Mw(8200): 17 ms
01-18 17:26:07.414: V/Mw(8200): 16 ms
01-18 17:26:07.434: V/Mw(8200): 16 ms
01-18 17:26:07.444: V/Mw(8200): 17 ms
01-18 17:26:07.464: V/Mw(8200): 17 ms
01-18 17:26:07.484: V/Mw(8200): 16 ms
01-18 17:26:07.494: V/Mw(8200): 17 ms
01-18 17:26:07.514: V/Mw(8200): 16 ms
01-18 17:26:07.534: V/Mw(8200): 16 ms
01-18 17:26:07.545: V/Mw(8200): 17 ms
01-18 17:26:07.565: V/Mw(8200): 16 ms
01-18 17:26:07.585: V/Mw(8200): 16 ms
01-18 17:26:07.595: V/Mw(8200): 17 ms
01-18 17:26:07.615: V/Mw(8200): 16 ms
01-18 17:26:07.635: V/Mw(8200): 16 ms
01-18 17:26:07.645: V/Mw(8200): 17 ms
01-18 17:26:07.665: V/Mw(8200): 17 ms
01-18 17:26:07.685: V/Mw(8200): 16 ms
01-18 17:26:07.695: V/Mw(8200): 17 ms
01-18 17:26:07.715: V/Mw(8200): 17 ms
01-18 17:26:07.735: V/Mw(8200): 16 ms
01-18 17:26:07.745: V/Mw(8200): 17 ms
01-18 17:26:07.765: V/Mw(8200): 17 ms
01-18 17:26:07.785: V/Mw(8200): 16 ms
01-18 17:26:07.795: V/Mw(8200): 17 ms
01-18 17:26:07.815: V/Mw(8200): 17 ms
01-18 17:26:07.835: V/Mw(8200): 16 ms
01-18 17:26:07.845: V/Mw(8200): 16 ms
01-18 17:26:07.865: V/Mw(8200): 16 ms
01-18 17:26:07.885: V/Mw(8200): 17 ms
01-18 17:26:07.895: V/Mw(8200): 17 ms
01-18 17:26:07.915: V/Mw(8200): 17 ms
01-18 17:26:07.935: V/Mw(8200): 16 ms
01-18 17:26:07.945: V/Mw(8200): 17 ms
01-18 17:26:07.965: V/Mw(8200): 17 ms
01-18 17:26:07.985: V/Mw(8200): 16 ms
01-18 17:26:07.995: V/Mw(8200): 18 ms
01-18 17:26:08.015: V/Mw(8200): 17 ms
01-18 17:26:08.035: V/Mw(8200): 16 ms
01-18 17:26:08.045: V/Mw(8200): 17 ms
01-18 17:26:08.065: V/Mw(8200): 17 ms
01-18 17:26:08.085: V/Mw(8200): 16 ms
01-18 17:26:08.095: V/Mw(8200): 16 ms
01-18 17:26:08.115: V/Mw(8200): 17 ms
01-18 17:26:08.135: V/Mw(8200): 16 ms
01-18 17:26:08.145: V/Mw(8200): 17 ms
01-18 17:26:08.165: V/Mw(8200): 17 ms
01-18 17:26:08.185: V/Mw(8200): 16 ms
01-18 17:26:08.195: V/Mw(8200): 17 ms
01-18 17:26:08.215: V/Mw(8200): 17 ms
01-18 17:26:08.235: V/Mw(8200): 16 ms
01-18 17:26:08.245: V/Mw(8200): 16 ms
01-18 17:26:08.265: V/Mw(8200): 17 ms
01-18 17:26:08.285: V/Mw(8200): 16 ms
01-18 17:26:08.295: V/Mw(8200): 17 ms
01-18 17:26:08.315: V/Mw(8200): 17 ms
01-18 17:26:08.335: V/Mw(8200): 16 ms
01-18 17:26:08.345: V/Mw(8200): 17 ms
01-18 17:26:08.365: V/Mw(8200): 17 ms
01-18 17:26:08.385: V/Mw(8200): 16 ms
01-18 17:26:08.395: V/Mw(8200): 17 ms
01-18 17:26:08.415: V/Mw(8200): 17 ms
01-18 17:26:08.435: V/Mw(8200): 16 ms
01-18 17:26:08.445: V/Mw(8200): 17 ms
01-18 17:26:08.465: V/Mw(8200): 17 ms
01-18 17:26:08.486: V/Mw(8200): 16 ms
01-18 17:26:08.496: V/Mw(8200): 17 ms
01-18 17:26:08.516: V/Mw(8200): 17 ms
01-18 17:26:08.526: V/Mw(8200): 16 ms
01-18 17:26:08.536: V/Mw(8200): 18 ms
01-18 17:26:08.556: V/Mw(8200): 16 ms
01-18 17:26:08.576: V/Mw(8200): 17 ms
01-18 17:26:08.586: V/Mw(8200): 16 ms
01-18 17:26:08.616: V/Mw(8200): 17 ms
01-18 17:26:08.626: V/Mw(8200): 16 ms
01-18 17:26:08.636: V/Mw(8200): 17 ms
01-18 17:26:08.666: V/Mw(8200): 17 ms
01-18 17:26:08.686: V/Mw(8200): 16 ms
01-18 17:26:08.696: V/Mw(8200): 17 ms
01-18 17:26:08.716: V/Mw(8200): 17 ms
01-18 17:26:08.736: V/Mw(8200): 17 ms
01-18 17:26:08.746: V/Mw(8200): 16 ms
01-18 17:26:08.766: V/Mw(8200): 17 ms
01-18 17:26:08.786: V/Mw(8200): 16 ms
01-18 17:26:08.786: V/Mw(8200): 17 ms
01-18 17:26:08.806: V/Mw(8200): 17 ms
01-18 17:26:08.826: V/Mw(8200): 16 ms
01-18 17:26:08.846: V/Mw(8200): 17 ms
01-18 17:26:08.856: V/Mw(8200): 17 ms
01-18 17:26:08.876: V/Mw(8200): 16 ms
01-18 17:26:08.896: V/Mw(8200): 17 ms
01-18 17:26:08.926: V/Mw(8200): 25 ms
01-18 17:26:08.936: V/Mw(8200): 8 ms
01-18 17:26:08.946: V/Mw(8200): 17 ms
01-18 17:26:08.956: V/Mw(8200): 17 ms
01-18 17:26:08.986: V/Mw(8200): 16 ms
01-18 17:26:09.006: V/Mw(8200): 36 ms
01-18 17:26:09.026: V/Mw(8200): 10 ms
01-18 17:26:09.036: V/Mw(8200): 21 ms
01-18 17:26:09.056: V/Mw(8200): 8 ms
01-18 17:26:09.086: V/Mw(8200): 27 ms
01-18 17:26:09.096: V/Mw(8200): 17 ms
01-18 17:26:09.116: V/Mw(8200): 25 ms
01-18 17:26:09.136: V/Mw(8200): 16 ms
01-18 17:26:09.146: V/Mw(8200): 19 ms
01-18 17:26:09.156: V/Mw(8200): 7 ms
01-18 17:26:09.186: V/Mw(8200): 14 ms
01-18 17:26:09.186: V/Mw(8200): 16 ms
01-18 17:26:09.206: V/Mw(8200): 17 ms
01-18 17:26:09.236: V/Mw(8200): 16 ms
01-18 17:26:09.246: V/Mw(8200): 15 ms
01-18 17:26:09.256: V/Mw(8200): 17 ms
01-18 17:26:09.286: V/Mw(8200): 16 ms
01-18 17:26:09.296: V/Mw(8200): 24 ms
01-18 17:26:09.326: V/Mw(8200): 17 ms
01-18 17:26:09.336: V/Mw(8200): 17 ms
01-18 17:26:09.346: V/Mw(8200): 18 ms
01-18 17:26:09.366: V/Mw(8200): 15 ms
01-18 17:26:09.396: V/Mw(8200): 26 ms
01-18 17:26:09.406: V/Mw(8200): 15 ms
01-18 17:26:09.427: V/Mw(8200): 24 ms
01-18 17:26:09.457: V/Mw(8200): 18 ms
01-18 17:26:09.477: V/Mw(8200): 19 ms
01-18 17:26:09.477: V/Mw(8200): 13 ms
01-18 17:26:09.507: V/Mw(8200): 17 ms
01-18 17:26:09.527: V/Mw(8200): 18 ms
01-18 17:26:09.547: V/Mw(8200): 17 ms
01-18 17:26:09.557: V/Mw(8200): 14 ms
01-18 17:26:09.577: V/Mw(8200): 15 ms
01-18 17:26:09.587: V/Mw(8200): 24 ms
01-18 17:26:09.607: V/Mw(8200): 14 ms
01-18 17:26:09.617: V/Mw(8200): 10 ms
01-18 17:26:09.657: V/Mw(8200): 35 ms
01-18 17:26:09.667: V/Mw(8200): 15 ms
01-18 17:26:09.687: V/Mw(8200): 20 ms
01-18 17:26:09.697: V/Mw(8200): 10 ms
01-18 17:26:09.727: V/Mw(8200): 18 ms
01-18 17:26:09.737: V/Mw(8200): 16 ms
01-18 17:26:09.757: V/Mw(8200): 16 ms
01-18 17:26:09.777: V/Mw(8200): 24 ms
01-18 17:26:09.787: V/Mw(8200): 17 ms
01-18 17:26:09.807: V/Mw(8200): 14 ms
01-18 17:26:09.817: V/Mw(8200): 10 ms
01-18 17:26:09.847: V/Mw(8200): 21 ms
01-18 17:26:09.847: V/Mw(8200): 12 ms
01-18 17:26:09.887: V/Mw(8200): 33 ms
01-18 17:26:09.897: V/Mw(8200): 14 ms
01-18 17:26:09.937: V/Mw(8200): 35 ms
01-18 17:26:09.947: V/Mw(8200): 15 ms
01-18 17:26:09.957: V/Mw(8200): 11 ms
01-18 17:26:09.977: V/Mw(8200): 20 ms
01-18 17:26:09.987: V/Mw(8200): 12 ms
01-18 17:26:10.007: V/Mw(8200): 18 ms
01-18 17:26:10.027: V/Mw(8200): 15 ms
01-18 17:26:10.047: V/Mw(8200): 17 ms
01-18 17:26:10.057: V/Mw(8200): 17 ms
01-18 17:26:10.077: V/Mw(8200): 16 ms
01-18 17:26:10.097: V/Mw(8200): 17 ms
01-18 17:26:10.107: V/Mw(8200): 17 ms
01-18 17:26:10.127: V/Mw(8200): 16 ms
01-18 17:26:10.147: V/Mw(8200): 17 ms
01-18 17:26:10.157: V/Mw(8200): 17 ms
01-18 17:26:10.177: V/Mw(8200): 16 ms
01-18 17:26:10.207: V/Mw(8200): 31 ms
01-18 17:26:10.217: V/Mw(8200): 10 ms
01-18 17:26:10.257: V/Mw(8200): 32 ms
01-18 17:26:10.277: V/Mw(8200): 18 ms
01-18 17:26:10.287: V/Mw(8200): 18 ms
01-18 17:26:10.307: V/Mw(8200): 13 ms
01-18 17:26:10.327: V/Mw(8200): 20 ms
01-18 17:26:10.337: V/Mw(8200): 19 ms
01-18 17:26:10.347: V/Mw(8200): 11 ms
01-18 17:26:10.388: V/Mw(8200): 35 ms
01-18 17:26:10.388: V/Mw(8200): 6 ms
01-18 17:26:10.408: V/Mw(8200): 17 ms
01-18 17:26:10.428: V/Mw(8200): 16 ms
01-18 17:26:10.448: V/Mw(8200): 16 ms
01-18 17:26:10.458: V/Mw(8200): 16 ms
01-18 17:26:10.508: V/Mw(8200): 47 ms
01-18 17:26:10.518: V/Mw(8200): 8 ms
01-18 17:26:10.528: V/Mw(8200): 12 ms
01-18 17:26:10.538: V/Mw(8200): 15 ms
01-18 17:26:10.558: V/Mw(8200): 17 ms
01-18 17:26:10.578: V/Mw(8200): 16 ms
01-18 17:26:10.598: V/Mw(8200): 20 ms
01-18 17:26:10.608: V/Mw(8200): 14 ms
01-18 17:26:10.628: V/Mw(8200): 17 ms
01-18 17:26:10.648: V/Mw(8200): 16 ms
01-18 17:26:10.658: V/Mw(8200): 16 ms
01-18 17:26:10.678: V/Mw(8200): 22 ms
01-18 17:26:10.698: V/Mw(8200): 18 ms
01-18 17:26:10.718: V/Mw(8200): 18 ms
01-18 17:26:10.738: V/Mw(8200): 15 ms
01-18 17:26:10.758: V/Mw(8200): 23 ms
01-18 17:26:10.778: V/Mw(8200): 23 ms
01-18 17:26:10.808: V/Mw(8200): 26 ms
01-18 17:26:10.828: V/Mw(8200): 19 ms
01-18 17:26:10.848: V/Mw(8200): 17 ms
01-18 17:26:10.858: V/Mw(8200): 16 ms
01-18 17:26:10.888: V/Mw(8200): 30 ms
01-18 17:26:10.898: V/Mw(8200): 6 ms
01-18 17:26:10.928: V/Mw(8200): 29 ms
01-18 17:26:10.948: V/Mw(8200): 16 ms
01-18 17:26:10.958: V/Mw(8200): 16 ms
01-18 17:26:10.978: V/Mw(8200): 22 ms
01-18 17:26:10.988: V/Mw(8200): 13 ms
01-18 17:26:11.008: V/Mw(8200): 14 ms
01-18 17:26:11.028: V/Mw(8200): 16 ms
rtrussell
2017-01-18 17:05:54 UTC
Permalink
I get iterations from 6 ms to 47 ms. ( see list ). I think v-sync isn't working here. Am I wrong ?
Your measurements will be affected by the time taken in __android_log_print, and I wouldn't be surprised if it is variable. To be certain your conclusion is valid I would prefer to see you measure the actual frame period:


Code:
time2 = SDL_GetTicks();
while (1)
{
SDL_RenderClear( m_renderer );
SDL_RenderCopy( m_renderer, rawTexture, &SDL_srcRect, &SDL_destRect );
SDL_RenderPresent( m_renderer );

time1 = time2;
time2 = SDL_GetTicks();
time3 = time2 - time1;

ostringstream sstream;
sstream << time3 << " ms";
text = sstream.str();
__android_log_print ( ANDROID_LOG_VERBOSE, "Mw", text.c_str() );
}


Richard.
Edition Chamäleon
2017-01-21 00:27:44 UTC
Permalink
Hi there,
is there anyone out there who has a clue why in my case (see above) SDL on Android gives such uneven iteration time, even if vsync is on and there is almost nothing drawn or calculated? I'm running out of ideas here.

Michael
Eric Wing
2017-01-21 01:38:32 UTC
Permalink
Post by Edition Chamäleon
Hi there,
is there anyone out there who has a clue why in my case (see above) SDL on
Android gives such uneven iteration time, even if vsync is on and there is
almost nothing drawn or calculated? I'm running out of ideas here.
Michael
Here's a few thoughts:

- On Android, SDL is (tragically) running on a background thread and
not the main UI thread. So when the vsync happens, it may not occur on
your thread. So you may not actually be measuring what you think you
are.

- Some graphics drivers may not block for the entire actual draw at
your RenderPresent call. So the draw call may return quickly/early,
and the under the hood, the video card does things asynchronously or
defers the drawing, perhaps to the real vsync. So again, you may not
be measuring what you think you are.

- In both the above cases, you are timing just the rendering call, and
not the time it takes to go through the entire game loop for that
frame. If the graphics system is rendering at a different time, you
skip measuring the real drawing time. Usually this results in faster
(unrealistic) framerates and makes the benchmarks look fishy. (I think
I remember Pixi.js BunnyMark did this and the reported numbers were
way over inflated than what was actually going on. I'm not sure what's
going on in your case, but I think you should also try measuring the
time between the start of each loop. I would not be looking for an
exact 16 ms, but I would be looking for numbers less than that.


- A very long time ago, I had to use a really poor C++ compiler with a
crap library implementation. ostringstream was ridiculously slow. The
Android NDK is also notorious for having crap implementations in their
standard libraries, so it wouldn't surprise me if ostringstream was
slow. Just use SDL_snprintf or something simpler.

- Try looking for an Android tool (DDMS?) that can measure frame rate
for you and compare your numbers to see if they are the same.

- Avoid setting SDL_RENDERER_ACCELERATED and SDL_THREAD_PRIORITY_HIGH
and try/trust the defaults. I think SDL_RENDERER_ACCELERATED is
supposed to be the default, but try ruling out a bug where the flag
makes it slower. And mucking with the thread priorities can be very
unpredictable depending on the platform's scheduler and you could be
shooting yourself in the foot with that.

- Also try ditching the SDL_WINDOW_BORDLESS and SDL_WINDOW_OPENGL.

- Try using smaller textures. If you have too high a texture
resolution, you might be getting killed in fill rate.

- Try setting the color and bit depths differently.
https://wiki.libsdl.org/SDL_GL_SetAttribute

- Maybe you should be calling SDL_PollEvent to make sure the SDL event
queue is getting cleared and not having to deal with overflow
avoidance.

- Your log printing can also overwhelm the system. You might consider
only printing every second or two and print the average in that
duration.

- Try using the SDL_PerformanceCounter instead of SDL_GetTicks. I
doubt it is going to matter here, but the former was designed for
performance measurements like you are doing here.

-Eric
Rainer Deyke
2017-01-21 10:24:27 UTC
Permalink
Hi there, is there anyone out there who has a clue why in my case
(see above) SDL on Android gives such uneven iteration time, even if
vsync is on and there is almost nothing drawn or calculated?
Why wouldn't it?

Here is how correct triple buffering with vsync works:
- There are three buffers: the buffer currently being sent to the
screen (the "screen buffer"), the buffer to which the game is currently
rendering (the "back buffer"), and the third buffer (the "spare
buffer"). There is also an "enqueued" bit which indicates if the spare
buffer is enqueued for being sent to the screen.
- On RenderPresent, the system does this:
- Optionally wait for the enqueued bit to be cleared.
- The back buffer and the spare buffer exchange places.
- The enqueued bit is set.
- Meanwhile, the video hardware is in an endless loop:
- Send screen buffer to physical screen.
- If the enqueued bit is set:
- Clear it.
- The screen buffer and spare buffer exchange places.
- Repeat.

If the game renders slower than the display refresh rate, then the time
per frame will always be uneven. If the game renders faster than the
display refresh rate, then the time per frame may or may not be uneven
depending on whether the display driver chooses to wait for the enqueued
bit to be cleared. (Waiting saves battery time and ensures that every
rendered frame is sent to the screen but increases display latency, so
there are good reason both for and against waiting. For a mobile
device, I would expect the reasons for waiting to outweigh the reasons
against waiting.)
--
Rainer Deyke - ***@eldwood.com
rtrussell
2017-01-21 12:10:45 UTC
Permalink
- Optionally wait for the enqueued bit to be cleared...
Surely, when SDL_RENDERER_PRESENTVSYNC is set, SDL_RenderPresent must wait. That's the only thing which synchronises the app's rendering to the hardware display rate. If it didn't wait the total number of calls to SDL_RenderPresent could exceed the total number of frames displayed! Or did I misunderstand your description?

Richard.
Edition Chamäleon
2017-01-21 20:44:22 UTC
Permalink
Hi together,

and thank you very much for your thoughts and hints. I appreciate very much.
I'm not sure what's going on in your case, but I think you should also try measuring the time between the start of each loop. I would not be looking for an exact 16 ms, but I would be looking for numbers less than that."
In my case the gameloop runs fluidly most of the time, but it stucks one to two times per second, so that the scrolling jerks. Meaning the gameloop with all grafic rendering can be done in 16ms most of the iterations. But only on Android. For me an indication, that my gameloop is not to long in principle. It seemed to me, that something from extern or SDL timer disturbs my game. That SDL runns on a backgroundthread fits here.
To investigate this guess more closely I made this minimal programm above with almost no calculations in gameloop, which shows uneven iteration times. And very big deviation ( e.g. 45ms ) one or two times a second either.
"Try using smaller textures. If you have too high a texture resolution, you might be getting killed in fill rate.
This is not realy an option. The problem with the uneven v-sync accures even when rendering only a single texture with only very low resolution. Rendering even less than that means rendering nothing.

The SDL_THREAD_PRIORITY option had no impact in my case, so I removed it. SDL_RENDER_ACCELERATED is true on default, SDL_WINDOW_BORDERLESS and SDL_WINDOW_OPENGL is on in my case.

I will look into SDL_PerformanceCounter and SDL_PollEvent, didn't know about this features till now.



@Rainer Deyke
If the game renders slower than the display refresh rate, then the time
per frame will always be uneven.
Waiting saves battery time
I don't think, my gameloop takes more than 16ms for calculations and rendering, because most of the iterations are done fluidly in 16ms and the work per itartion is always the same. But one to two times per second the scrolling jerks an I measure fps from up to 45ms. But only for one or two iterations. It doesn't look like a battery save action to me, more a disturbance from extern or a timer problem. To underpin my guess I measured the minimal programm above. It shows the same problem, even with already no calculation and minimal rendering.


I thank you all for your time and your ideas. Please tell me more, because I am not yet on homebase. :)
Rainer Deyke
2017-01-22 13:15:10 UTC
Permalink
Post by rtrussell
- On RenderPresent, the system does this: - Optionally wait for the
enqueued bit to be cleared...
Surely, when SDL_RENDERER_PRESENTVSYNC is set, SDL_RenderPresent must
wait. That's the only thing which synchronises the app's rendering
to the hardware display rate. If it didn't wait the total number of
calls to SDL_RenderPresent could exceed the total number of frames
displayed!
It's a matter of definitions. Vsync means that the enqueued spare
buffer and the screen buffer are only exchanged during the "vertical
retrace" when a whole screen buffer has been presented to the screen,
thereby preventing the "tearing" that happens when half of the screen is
from one frame and the other half comes from a different frame. It is
the act of exchanging buffers which is synchronized, not the rendering
in the game. Dropping whole frames does not cause tearing, so it is
compatible with vsync as defined above. Another definition of vsync is
basically "as above, but no dropped frames allowed", in which case
dropping frames is obviously not allowed.

As for what SDL_RENDERER_PRESENTVSYNC actually does, I would assume that
depends on the underlying OS, graphics driver, and hardware. I don't
think SDL is required to honor SDL_RENDERER_PRESENTVSYNC at all, if the
underlying system doesn't support it.
--
Rainer Deyke - ***@eldwood.com
Luke Groeninger
2017-01-22 17:30:21 UTC
Permalink
It's a matter of definitions. Vsync means that the enqueued spare buffer and the screen buffer are only exchanged during the "vertical retrace" when a whole screen buffer has been presented to the screen, thereby preventing the "tearing" that happens when half of the screen is from one frame and the other half comes from a different frame. It is the act of exchanging buffers which is synchronized, not the rendering in the game. Dropping whole frames does not cause tearing, so it is compatible with vsync as defined above. Another definition of vsync is basically "as above, but no dropped frames allowed", in which case dropping frames is obviously not allowed.
Worth chiming in - that is incorrect not actually true. Vsync - in the context of graphics APIs - typically means that calls to present buffers are synchronized with the display presentation for timing purposes. In that context, silently dropping frames and allowing rendering to continue is a blatant violation of the API specification and will break applications that rely on that behavior. As a result, typically the method of triple buffering used is to simply treat the swap chain as a FIFO queue that is at max three long, and to simply block on submission if the queue is already full. This satisfies the behavioral requirements of the vsync APIs, while allowing buffering of additional frames.

To get more into the nitty gritty with an actual example - OpenGL uses the swap interval concept that specifies the *minimum* number of v-blanks that can occur between buffer swaps. In that case, the expected behavior when you call SwapBuffers with SwapInterval at a non-zero value is to block and wait until at least <n> v-blanks has passed since the last SwapBuffers call. As a result, triple buffering as you describe it is not possible when you have a non-zero swap interval.

With all that said, there are ways of getting the behavior you described with OpenGL *if* you have a compositor that behaves like this. I might be mistaken about this, but AFAIK this is how OS X and iOS behave when you have vsync disabled - but it’s because the compositor controls the “front buffer” and not your application, and they (if I remember right) always synchronize that buffer swap. I don’t know about Android, but it’s possible it does as well. The big question with compositing window managers is if they force synchronization during the compositing swap or not - if they do, you have to implement correct triple buffering in order not to block rendering during presents. If they don’t - because, for instance, an application has enabled adaptive v-sync, they typically fall back to double buffering and more traditional blocking behavior. It’s a crap shoot and you can’t really rely on the behavior to be consistent across platforms.

Direct3D apps can specify this behavior when creating their swap chain, and it is possible for the GL ICD on Windows to implement this behavior using DXGI, but again - there is no way to tell the ICD vendor that this is your desired behavior without using proprietary APIs or their driver control panel.

IIRC, Vulkan doesn’t support this feature yet but there is a proposal out there that will hopefully allow it.

But yes. Keep in mind the entire purpose of vsync is to allow the application to synchronize with the presentation on the display, and in that context the method of triple buffering you describe is mutually exclusive with an application requesting vsync to be enabled.

-Luke
Edition Chamäleon
2017-01-22 18:24:18 UTC
Permalink
Hello everybody,

since I am the one who has raised the subject, I allow myself to preside once again on my question:

As I understand, what VSYNC does in background is much more complex than simply waiting for retrace. Probably VSYNC does work correct in my case, because I do not have any problems with tearing screens. I actually do have a problem with uneven duration of iterations and with jerking Scrolling in result.

Till now I thought VSYNC would lead to regular iterations. On Android this is apparently not the case, so far I can see. But with iteration time of 45ms one or two times in a second, smooth movement isn't possible. And reducing the framerate to 45ms in general isn't a solution either, because then everything jerks all the time.


So here is my precised question:
Is there a way to prevent foreign Android processes from stealing SDL or my program to much time?


Thanx in advance, Michael

Loading...