Double buffer trouble

Hello,

I making a galaga-type 2D space shooter as a project to teach myself C++ and
I am stuck because I can’t get the framerate smooth. I have been trying to
solve this for two weeks now and frankly, I’m beginning to lose hope.

My problem is that I can’t get my sprites to move smoothly across the
screen. They move smoothly most of the time but once every second or so they
’jerk’, as if a frame was delayed. I have tried every solution I have been
able to find on this list and elsewhere on the net.
I have tried single buffers, double buffer and double buffer with an extra
sw-buffer. I have tried flipping, and blitting and even flipping from a
separate thread controlled by semaphores. I have implemented interpolation
of sprite movements.

I believe my problem is related to the Flip() becoming out of sync with the
VBlank. If I log the timing of the Flips I get 16 or 17 seconds per Flip and
now and then a larger number (e.g 22) followed by a lower number(e.g 12). It
may look like this: 16 16 17 17 16 17 16 16 20 12 16 17 16 16 … and so on.

This leads me to suspect the actual Flip is the culprit and that it’s
missing VBlank and then has to wait for the next one to flip the buffers.

This is an example code demonstrating this problem:

int main(int argc, char *argv[])
{
// Initialize SDL_Video and set the videomode to
// 1024x768 32bpp SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN

SDL_Event event;
int done=0;
int yVel=5;
SDL_Rect destrect;
destrect.x=400;
destrect.y=400;
int time0;

while (!done)
{
	if (SDL_PollEvent(&event))
		if (event.type == SDL_KEYDOWN)
			done=1;

	// check if blitted image is about to leave screen
	if ((destrect.y+yVel<700) && (destrect.y+yVel>0))
		destrect.y+=yVel;
	else	// if it is, invert velocity
		yVel*=-1;

	SDL_FillRect (screen, NULL, 0); 					SDL_BlitSurface(image, NULL, screen, 

&destrect);

	SDL_Flip(screen); // flip screen
	cout << SDL_GetTicks()-time0 << endl;
	time0=SDL_GetTicks();
}
return 0;

}

If SDL_Flip() actually does wait for VBlank then this piece of code, with
one update of the graphics for every flip and plenty of time to spare each
frame, should produce smooth framerate, shouldn’t it?

Well, it doesn’t. Every other second or so, the Flip misses VBlank and the
motion halts until next VBlank. At least not on my computer.

So, my question is: How do I make SDL_Flip() not miss VBlanks? or, Why does
SDL_Flip() miss VBlank even when it has plenty of time to wait for it?

Sorry for the long post, but this problem is driving me nuts!

//Martin, biologist and soon-to-be gardener of L?ck? castle._________________________________________________________________
MSN Photos is the easiest way to share and print your photos:
http://photos.msn.com/support/worldwide.aspx

I believe my problem is related to the Flip() becoming out of sync with the
VBlank. If I log the timing of the Flips I get 16 or 17 seconds per Flip and
now and then a larger number (e.g 22) followed by a lower number(e.g 12). It
may look like this: 16 16 17 17 16 17 16 16 20 12 16 17 16 16 … and so on.

This leads me to suspect the actual Flip is the culprit and that it’s
missing VBlank and then has to wait for the next one to flip the buffers.

What platform are you running on?

See ya,
-Sam Lantinga, Software Engineer, Blizzard Entertainment

For a galaga type game, I would suggest just tracking the frame time, and
using that to update the positions of objects. You can fix AI to a fixed
frame rate if you want, which you probably would want to do. Here’s the
basics of how it’s done (I do this in my game as well, so it does work. :slight_smile:

float frame_time = 0.0f;
Uint32 last_ticks = 0;

void flip()
{
Uint32 ticks;

ticks = SDL_GetTicks();
frame_time = (float) (ticks - last_ticks) / 1000.0f;
last_ticks = ticks;
SDL_Flip(screen);
}

You call this once a frame, instead of calling SDL_Flip() directly. You
will then always have the “frame_time” variable around, which is the time in
seconds of last frame, but good enough to use for the current frame.

You can update objects like so:

object->x += object->dx * frame_time;
object->y += object->dy * frame_time;

You want to make sure you use floats for both position and velocity values,
though.

The nice thing about this is that it doesn’t matter what FPS you are
getting. It could be 60, 75, some other constant, or fluctuate from time to
time. Your objects should still all move rather smoothly because you are
basing movements off of actual real time.

-Jason> ----- Original Message -----

From: heronridge@hotmail.com (Martin Hageras)
To:
Sent: Friday, March 22, 2002 12:52 PM
Subject: [SDL] Double buffer trouble…

Hello,

I making a galaga-type 2D space shooter as a project to teach myself C++
and
I am stuck because I can’t get the framerate smooth. I have been trying to
solve this for two weeks now and frankly, I’m beginning to lose hope.

My problem is that I can’t get my sprites to move smoothly across the
screen. They move smoothly most of the time but once every second or so
they
’jerk’, as if a frame was delayed. I have tried every solution I have been
able to find on this list and elsewhere on the net.
I have tried single buffers, double buffer and double buffer with an extra
sw-buffer. I have tried flipping, and blitting and even flipping from a
separate thread controlled by semaphores. I have implemented interpolation
of sprite movements.

I believe my problem is related to the Flip() becoming out of sync with
the
VBlank. If I log the timing of the Flips I get 16 or 17 seconds per Flip
and
now and then a larger number (e.g 22) followed by a lower number(e.g 12).
It
may look like this: 16 16 17 17 16 17 16 16 20 12 16 17 16 16 … and so
on.

This leads me to suspect the actual Flip is the culprit and that it’s
missing VBlank and then has to wait for the next one to flip the buffers.

This is an example code demonstrating this problem:

int main(int argc, char *argv[])
{
// Initialize SDL_Video and set the videomode to
// 1024x768 32bpp SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN

SDL_Event event;
int done=0;
int yVel=5;
SDL_Rect destrect;
destrect.x=400;
destrect.y=400;
int time0;

while (!done)
{
if (SDL_PollEvent(&event))
if (event.type == SDL_KEYDOWN)
done=1;

// check if blitted image is about to leave screen
if ((destrect.y+yVel<700) && (destrect.y+yVel>0))
destrect.y+=yVel;
else // if it is, invert velocity
yVel*=-1;

SDL_FillRect (screen, NULL, 0); SDL_BlitSurface(image, NULL, screen,
&destrect);

SDL_Flip(screen); // flip screen
cout << SDL_GetTicks()-time0 << endl;
time0=SDL_GetTicks();
}
return 0;
}

If SDL_Flip() actually does wait for VBlank then this piece of code, with
one update of the graphics for every flip and plenty of time to spare each
frame, should produce smooth framerate, shouldn’t it?

Well, it doesn’t. Every other second or so, the Flip misses VBlank and the
motion halts until next VBlank. At least not on my computer.

So, my question is: How do I make SDL_Flip() not miss VBlanks? or, Why
does
SDL_Flip() miss VBlank even when it has plenty of time to wait for it?

Sorry for the long post, but this problem is driving me nuts!

file://Martin, biologist and soon-to-be gardener of L?ck? castle.


MSN Photos is the easiest way to share and print your photos:
http://photos.msn.com/support/worldwide.aspx


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

[…]

If SDL_Flip() actually does wait for VBlank then this piece of code,
with one update of the graphics for every flip and plenty of time to
spare each frame, should produce smooth framerate, shouldn’t it?

Yep.

Well, it doesn’t. Every other second or so, the Flip misses VBlank and
the motion halts until next VBlank. At least not on my computer.

So, my question is: How do I make SDL_Flip() not miss VBlanks? or, Why
does SDL_Flip() miss VBlank even when it has plenty of time to wait for
it?

This basically sounds like an OS, driver and/or hardware problem - and
I’m afraid there’s nothing much to do about it, short of taking
Linux/lowlatency, hacking the drivers and running your application and
the X server at real time priority.

First, kill off any background applications that might want to do
something every now and then. Because you’re basically hogging the CPU
100%, Windows will just stop your process and let the others run until
they block, whenever they wake up. Not even WinNT “real time” priority
will entirely protect you from that, and it seems like Windows is too
stupid to do the right thing regardless of whether retrace sync is done
by busy-waiting or proper (IRQ based) blocking.

Another thing you might check is how much of the frame time is used for
rendering. (This includes any “fake” flipping with blits!) If you’re
using too much, that would explain why even the slightest “hickup” that
delays your game will result in a dropped frame - you simply can’t render
and flip in time, if you’re too late!

Triple buffering should help a lot, if this is the problem. As an
alternative to hacking a (currently) DirectX specific feature into SDL,
you could try using OpenGL (directly or through glSDL), as that
inherently adds a great deal of extra buffering (ie more “slack”) in the
form of the accelerator command buffer.

If nothing helps, I’m suspecting that your driver is straight polling the
retrace status, which will result in missed retraces if there’s as much
as a kernel driver IRQ in use. You could try to find another driver
and/or video card, that does retrace sync in a more reliable way… (If
the hardware somehow buffers the retrace “event”, it shouldn’t matter if
the driver is a few ms late - the “event” will still be there for the
driver to see. A card with retrace IRQ would have been just fine - if
there were any these days… heh)

//David Olofson — Programmer, Reologica Instruments AB

.- M A I A -------------------------------------------------.
| Multimedia Application Integration Architecture |
| A Free/Open Source Plugin API for Professional Multimedia |
----------------------------> http://www.linuxdj.com/maia -' .- David Olofson -------------------------------------------. | Audio Hacker - Open Source Advocate - Singer - Songwriter |-------------------------------------> http://olofson.net -'On Friday 22 March 2002 18:52, Martin H?ger?s wrote:

I believe my problem is related to the Flip() becoming out of sync with
the

VBlank. If I log the timing of the Flips I get 16 or 17 seconds per Flip
and

now and then a larger number (e.g 22) followed by a lower number(e.g
12). It

may look like this: 16 16 17 17 16 17 16 16 20 12 16 17 16 16 … and so
on.

This leads me to suspect the actual Flip is the culprit and that it’s
missing VBlank and then has to wait for the next one to flip the
buffers.

What platform are you running on?

Heh, with 16 seconds between flips, he’s missing a LOT of VBlanks. :slight_smile:

-Jason

----- Original Message -----
From: slouken@devolution.com (Sam Lantinga)
To:
Sent: Friday, March 22, 2002 1:18 PM
Subject: Re: [SDL] Double buffer trouble…

Sam Latinga wrote:

What platform are you running on?

I’m on a p3-450 running Windows 2000, my graphics card is a Matrox G400.

Jason Hoffos wrote:

void flip()
{
Uint32 ticks;

ticks = SDL_GetTicks();
frame_time = (float) (ticks - last_ticks) / 1000.0f;
last_ticks = ticks;
SDL_Flip(screen);
}

You call this once a frame, instead of calling SDL_Flip() directly.

Youwill then always have the “frame_time” variable around, which is >the
time in seconds of last frame, but good enough to use for the >current
frame.

Well, I have tried that (though I used QueryPerformanceTimer) and it makes
the actual movement of the sprites very smooth but the ‘jerks’ are still
very visible.

David Olofsson wrote:

This basically sounds like an OS, driver and/or hardware problem - >and=20
I’m afraid there’s nothing much to do about it, short of taking=20
Linux/lowlatency, hacking the drivers and running your application >and=20
the X server at real time priority.

Well, like I said I’m on W2k and I haven’t experienced any similar problem
with other games or software.

Another thing you might check is how much of the frame time is used >for=20
rendering. (This includes any “fake” flipping with blits!) If you’re=20
using too much, that would explain why even the slightest “hickup” >that=20
delays your game will result in a dropped frame - you simply can’t >render
and flip in time, if you’re too late!

I thought that was the problem too until I made this little example code i
included in my original post. There is really NO way that that code will
prevent the Flip from staying in sync. If I comment out the Flip the code
runs a full loop in 2 ms, including the blit. That should be fast enough,
don’t you think?
And still the Flip misses sync now and then.

As for shutting down other processes to make my app run smooth, I never have
to do that running other apps. I can watch fullscreen video just fine and I
haven’t seen this ‘flip-jerk’ in any game i have played. At least some of
them must’ve used buffer-flipping with VSync…

Shutting down processes on W2k is easier said than done too. It seems almost
everything is ‘Access denied’ when you try to terminate it, even if you’re
logged in as administrator.

Matrox G400 is not a poor video card either so I find it hard to believe
that it’s to blame. Or the drivers.

Does the code I included in my post run smoothly on your system?

If it does I guess I’ll have to abandon SDL and try DirectX or OpenGL… :frowning:

This is a nive active list :slight_smile:

Cappy hoding, Martin._________________________________________________________________
Send and receive Hotmail on your mobile device: http://mobile.msn.com

[…]

David Olofsson wrote:

This basically sounds like an OS, driver and/or hardware problem -

and=20 I’m afraid there’s nothing much to do about it, short of
taking=20 Linux/lowlatency, hacking the drivers and running your
application >and=20 the X server at real time priority.

Well, like I said I’m on W2k and I haven’t experienced any similar
problem with other games or software.

What other games and software would that be? (As far as I have seen, only
3D games support sub-pixel accurate rendering - most 2D games just round
timer controlled positions to the nearest pixel, which results in more or
less frequent “jerking”, in the few cases where you don’t just get
constant jittering.)

Another thing you might check is how much of the frame time is used

for=20 rendering. (This includes any “fake” flipping with blits!) If
you’re=20 using too much, that would explain why even the slightest
"hickup" >that=20 delays your game will result in a dropped frame -
you simply can’t >render and flip in time, if you’re too late!

I thought that was the problem too until I made this little example
code i included in my original post. There is really NO way that that
code will prevent the Flip from staying in sync. If I comment out the
Flip the code runs a full loop in 2 ms, including the blit. That should
be fast enough, don’t you think?

Yeah…

And still the Flip misses sync now and then.

As for shutting down other processes to make my app run smooth, I never
have to do that running other apps. I can watch fullscreen video just
fine

I’ve never seen smooth video on any “normal” hardware… (You need a
serious CPU, or dedicated h/w to translate from the video frame rate to
the display frame rate.)

and I haven’t seen this ‘flip-jerk’ in any game i have played.

Are you sure they aren’t just doing the timing “compensation” well enough
that you can’t tell the occasional dropped frame from the constant
jittering? (Sub-pixel accurate rendering is the only way to get
perfectly smooth animation without relying on a fixed refresh rate -
unless you just let the game speed be dictated by whatever refresh rate
you get. heh)

At least some of them must’ve used buffer-flipping with VSync…

Most probably, yes…

Shutting down processes on W2k is easier said than done too. It seems
almost everything is ‘Access denied’ when you try to terminate it, even
if you’re logged in as administrator.

That would mostly be for system processes that you can’t really shut down
anyway, without more or less killing the system, AFAIK… I was rathe
thinking about the little evil things that show up as icons next to the
clock - and the clock itself, for that matter!

Matrox G400 is not a poor video card either so I find it hard to
believe that it’s to blame. Or the drivers.

Well, in my experience, it’s rather slow, and all OpenGL drivers are more
or less useless for serious applications (multiple contexts cannot be
accelerated for reasons apparently unknown even to Matrox…), but that’s
another story… Great 2D, rather high 3D rendering quality, and great
RAMDACs.

(The latter is the main reason why I’m using one - can’t bl**dy well
drive a $2500 monitor with nVidia’s excuses for RAMDACs. :frowning: If there’s
any news, I’m still interested, BTW. Any improvement above 1600x1200 with
GeForce4…?)

Does the code I included in my post run smoothly on your system?

No need to even test it - I’m on an XFree86/Linux system with standard
drivers, so there’s no retrace sync at all… However, when running Kobo
Deluxe on a 100 Hz display, the only “jerking” I can remember seeing is
the occasional pixel skip caused by the drift between the timer and the
refresh rate. (The game fixes the scrolling speed to the internal 30 ms
logic frame cycle, of course - the 100 Hz modes on that machine just
happen to match the resulting speed very well.)

I’ll have a look at how my Win98 + GeForce machine behaves this weekend,
though. (I’m thinking about this sub-pixel accurate ultra smooth
scrolling demo - but I might as well check this out while I’m at it.)

If it does I guess I’ll have to abandon SDL and try DirectX or
OpenGL… :frowning:

If you get any difference at all with DirectX, there’s a bug in SDL.
Possible of course, but it seems rather unlikely to me in this case.
(What could possibly cause something like this…?) If there is one, I
can’t see why it couldn’t be fixed.

Oh, triple buffering might make a difference, but I doubt it, as your
problem remains even if the rendering takes only a fraction of each
frame. (Triple buffering woul cut you some more slack, but considering
the timings you posted, it might not be sufficient.)

As to OpenGL, that may well make a difference, as you’re doing everything
more or less asynchronously, leaving buffering, flipping etc entirely to
the driver. However, no need to drop SDL to use OpenGL! :slight_smile:

//David Olofson — Programmer, Reologica Instruments AB

.- M A I A -------------------------------------------------.
| Multimedia Application Integration Architecture |
| A Free/Open Source Plugin API for Professional Multimedia |
----------------------------> http://www.linuxdj.com/maia -' .- David Olofson -------------------------------------------. | Audio Hacker - Open Source Advocate - Singer - Songwriter |-------------------------------------> http://olofson.net -'On Friday 22 March 2002 22:49, Martin H?ger?s wrote:

I checked the timing of my code a little closer and I realized that
SDL_Flip() does not really miss a VBlank, it just makes a delay once in a
while. The delay must happen before the flip which is why it’s visible as
jerky framerate. This explains why my loop timings looked like they did: 16
or 17 ms for most frames (corresponding to my 60Hz video refresh rate) and
once in a ‘slower’ frame immediately followed by a ‘faster’ one. Like so:
…16, 17, 16, 16, 20 (16+4), 12 (16-4), 16, 16, 16…

I noticed that whenever a frame takes longer that 16ms, the next frame is
faster by the same amount. So it would seem the the Flip() return late from
the flip and thus it has to wait less for the next VBlank.
If the Flip was acutally missing VBlank, the ‘slower’ frames should take
twice as long (16.666*2=33ms), and the following frame should not be
affected.
So what does this behavior suggest? Since the effect of these timing
differences is visible on screen the actual buffer-flip must be delayed. And
that must mean the the VSync is delayed?! Can this really be the case?

I don’t really know the workings of the VSync of the video card so perhaps
the above reasoning is wrong. I don’t see how a delay in the flip can cause
a delay in the actual screen-output without missing an entire VBlank period
though.

By the way, I’m getting the SDL list in ‘digest’ format so I can’t reply to
individual postings. How do I make my post stay in thread?

//Martin, liked the Amiga better…the Copper…sighs deeply_________________________________________________________________
Get your FREE download of MSN Explorer at http://explorer.msn.com/intl.asp.

You call this once a frame, instead of calling SDL_Flip() directly.

Youwill then always have the “frame_time” variable around, which is >the
time in seconds of last frame, but good enough to use for the >current
frame.

Well, I have tried that (though I used QueryPerformanceTimer) and it makes
the actual movement of the sprites very smooth but the ‘jerks’ are still
very visible.

Use something else. I had quite some problems with QueryPerformanceCounter on
Win2K, when I used timeGetTime it work without jerks.

Florian

Exactly same problem here (Linux, XFree86, Voodoo3, K6-2 500). In all my
programs I make sync that way;

t1=SDL_GetTicks()
t=t0-t1
t0=t1
physics(t)

and animation is “almost smooth”, with “jumps/delays”. Just like you I checked
"t" value and it changes. On faster computer there is no “jumps/delays” at all.

But the most annoying thing is that I can’t see this effect in other SDL games!
lbreakout has smooth animation, no problem with skobo or OpenGL shooters. I
never found any special code in games I’ve checked. And my idea was to calc
"mean" of latest “t values”, but I think it will destroy physics (different
game on different computers).On Fri, Mar 22, 2002 at 05:52:40PM +0000, Martin H?ger?s wrote:

My problem is that I can’t get my sprites to move smoothly across the
screen. They move smoothly most of the time but once every second or so they
’jerk’, as if a frame was delayed.


decopter - free SDL/OpenGL simulator under heavy development
download it from http://decopter.sourceforge.net

So, my question is: How do I make SDL_Flip() not miss VBlanks? or, Why
does SDL_Flip() miss VBlank even when it has plenty of time to wait for
it?

This basically sounds like an OS, driver and/or hardware problem - and
I’m afraid there’s nothing much to do about it, short of taking
Linux/lowlatency, hacking the drivers and running your application and
the X server at real time priority.

We are still not focussing on his issue with this answer, though: How does he make it work with the currently available solutions? No other
kernels/drivers/hacked-solutions will work, because people who download his ‘game’ will not be able to run it the same way he does. Please
remember we are creating games for people to play, not for some custom-hacked OS-specific solution…

First, kill off any background applications that might want to do
something every now and then. Because you’re basically hogging the CPU
100%, Windows will just stop your process and let the others run until
they block, whenever they wake up. Not even WinNT “real time” priority
will entirely protect you from that, and it seems like Windows is too
stupid to do the right thing regardless of whether retrace sync is done
by busy-waiting or proper (IRQ based) blocking.

It’s not Windows that is stupid here: It is assuming you are waisting the OS time, and punishes you for that. Windows assumes all applications
should work together, with respect to each other. If you want a real-time OS, don’t use Windows. Or do not expect that behaviour from Windows,
which would make more sense. Since a lot of people are using Windows, let’s just keep it at Windows then. And after, that, respect the
shortcomings of the OS, don’t complain about it all the time, instead try to find a way to live with it. No bashing about it’s process/thread-priority-
handling will help anyone to make smooth games. A proper solution-suggestion would do better.

Another thing you might check is how much of the frame time is used for
rendering. (This includes any “fake” flipping with blits!)

Fake flipping with blits? How does this apply to Windows then… He is just flipping hardware-wise, no fake or anything like that. This is
Windows… Not some X-bla-bla-Free86-version-6-point-9999 build not supporting hardware-double-buffering.

If you’re
using too much, that would explain why even the slightest “hickup” that
delays your game will result in a dropped frame - you simply can’t render
and flip in time, if you’re too late!

Ah, and that’s very true, indeed.

Triple buffering should help a lot, if this is the problem. As an
alternative to hacking a (currently) DirectX specific feature into SDL,
you could try using OpenGL (directly or through glSDL), as that
inherently adds a great deal of extra buffering (ie more “slack”) in the
form of the accelerator command buffer.

Triple buffering will still get you hooked up if you can’t manage to finish the third buffer in time, although, mathematically seen, this could only
happen twice less times than with double buffering. Apart from that, I would not suggest using OpenGL instead of DirectDraw all the time: It
involves a lot of work, even more than just finding a way to work with DirectDraw/SDL properly. Also, you are almost suggesting using OpenGL
instead of DirectDraw wouldn’t be that much work, but it really is. There are a lot of libraries already written to do this ‘2D-in-OpenGL’-wrapping
thing, which are far better than SDL, but they are just not always better, let alone the same. Don’t underestimate OpenGL, I would say!

If nothing helps, I’m suspecting that your driver is straight polling the
retrace status, which will result in missed retraces if there’s as much
as a kernel driver IRQ in use. You could try to find another driver
and/or video card, that does retrace sync in a more reliable way… (If
the hardware somehow buffers the retrace “event”, it shouldn’t matter if
the driver is a few ms late - the “event” will still be there for the
driver to see. A card with retrace IRQ would have been just fine - if
there were any these days… heh)

Well, I wouldn’t say this is happening on a Windows system, since these drivers always, currently, deliver rock-solid steady framerates, without
any artifact visible. And again: What is the use of having 1 card that fits your needs, when no one else has that card? You can code an
application that behaves correctly with your graphics card, but almost no one else will be able to use it. I do not think that the original question
was how to get smooth-running frames on one set of hardware, but how to do it on any kind of hardware… So this IRQ business is not of
relevance here, then.

All in all, I understand that some people are frustrated by the incompatibilities between several hardware-drivers and OS’s, but let’s please keep
that seperate from this mailing list. What I mean is, if someone asks how to get proper double-buffering work, don’t brag about how current
hardware is non-compliant to some VBlank-IRQ issue or something like that, but let’s please help this person how to get this working with the
current solutions available. Letting people know you know your business is fine, but please, let’s keep it short, and especially, not repeated all
the time: We know by now that some OS’s are not meant for full-screen vsync’ed framerates, let’s focus on the next big thing: How do we live
with that fact? Instead of complaining about it…

So, help each other out, don’t distract from the subject all the time?

Martin H?ger?s wrote:

I checked the timing of my code a little closer and I realized that
SDL_Flip() does not really miss a VBlank, it just makes a delay once in
a while. The delay must happen before the flip which is why it’s
visible as jerky framerate. This explains why my loop timings looked
like they did: 16 or 17 ms for most frames (corresponding to my 60Hz
video refresh rate) and once in a ‘slower’ frame immediately followed by
a ‘faster’ one. Like so:
…16, 17, 16, 16, 20 (16+4), 12 (16-4), 16, 16, 16…

Do you grab a base time and then subtract it from the current time to
get these numbers, in which case the sample error will tend to settle
out. Or, are you keeping current/last time variables so that the sample
error can add or subtract on each frame and give you want looks like
random frame time variations?

	Bob Pendleton

So, my question is: How do I make SDL_Flip() not miss VBlanks? or, Why
does SDL_Flip() miss VBlank even when it has plenty of time to wait for
it?

This basically sounds like an OS, driver and/or hardware problem - and
I’m afraid there’s nothing much to do about it, short of taking
Linux/lowlatency, hacking the drivers and running your application and
the X server at real time priority.

We are still not focussing on his issue with this answer, though: How does he make it work with the currently available solutions? No other
kernels/drivers/hacked-solutions will work, because people who download his ‘game’ will not be able to run it the same way he does. Please
remember we are creating games for people to play, not for some custom-hacked OS-specific solution…

First, kill off any background applications that might want to do
something every now and then. Because you’re basically hogging the CPU
100%, Windows will just stop your process and let the others run until
they block, whenever they wake up. Not even WinNT “real time” priority
will entirely protect you from that, and it seems like Windows is too
stupid to do the right thing regardless of whether retrace sync is done
by busy-waiting or proper (IRQ based) blocking.

It’s not Windows that is stupid here: It is assuming you are waisting the OS time, and punishes you for that. Windows assumes all applications
should work together, with respect to each other. If you want a real-time OS, don’t use Windows. Or do not expect that behaviour from Windows,
which would make more sense. Since a lot of people are using Windows, let’s just keep it at Windows then. And after, that, respect the
shortcomings of the OS, don’t complain about it all the time, instead try to find a way to live with it. No bashing about it’s process/thread-priority-
handling will help anyone to make smooth games. A proper solution-suggestion would do better.

Another thing you might check is how much of the frame time is used for
rendering. (This includes any “fake” flipping with blits!)

Fake flipping with blits? How does this apply to Windows then… He is just flipping hardware-wise, no fake or anything like that. This is
Windows… Not some X-bla-bla-Free86-version-6-point-9999 build not supporting hardware-double-buffering.

If you’re
using too much, that would explain why even the slightest “hickup” that
delays your game will result in a dropped frame - you simply can’t render
and flip in time, if you’re too late!

Ah, and that’s very true, indeed.

Triple buffering should help a lot, if this is the problem. As an
alternative to hacking a (currently) DirectX specific feature into SDL,
you could try using OpenGL (directly or through glSDL), as that
inherently adds a great deal of extra buffering (ie more “slack”) in the
form of the accelerator command buffer.

Triple buffering will still get you hooked up if you can’t manage to finish the third buffer in time, although, mathematically seen, this could only
happen twice less times than with double buffering. Apart from that, I would not suggest using OpenGL instead of DirectDraw all the time: It
involves a lot of work, even more than just finding a way to work with DirectDraw/SDL properly. Also, you are almost suggesting using OpenGL
instead of DirectDraw wouldn’t be that much work, but it really is. There are a lot of libraries already written to do this ‘2D-in-OpenGL’-wrapping
thing, which are far better than SDL, but they are just not always better, let alone the same. Don’t underestimate OpenGL, I would say!

If nothing helps, I’m suspecting that your driver is straight polling the
retrace status, which will result in missed retraces if there’s as much
as a kernel driver IRQ in use. You could try to find another driver
and/or video card, that does retrace sync in a more reliable way… (If
the hardware somehow buffers the retrace “event”, it shouldn’t matter if
the driver is a few ms late - the “event” will still be there for the
driver to see. A card with retrace IRQ would have been just fine - if
there were any these days… heh)

Well, I wouldn’t say this is happening on a Windows system, since these drivers always, currently, deliver rock-solid steady framerates, without
any artifact visible. And again: What is the use of having 1 card that fits your needs, when no one else has that card? You can code an
application that behaves correctly with your graphics card, but almost no one else will be able to use it. I do not think that the original question
was how to get smooth-running frames on one set of hardware, but how to do it on any kind of hardware… So this IRQ business is not of
relevance here, then.

All in all, I understand that some people are frustrated by the incompatibilities between several hardware-drivers and OS’s, but let’s please keep
that seperate from this mailing list. What I mean is, if someone asks how to get proper double-buffering work, don’t brag about how current
hardware is non-compliant to some VBlank-IRQ issue or something like that, but let’s please help this person how to get this working with the
current solutions available. Letting people know you know your business is fine, but please, let’s keep it short, and especially, not repeated all
the time: We know by now that some OS’s are not meant for full-screen vsync’ed framerates, let’s focus on the next big thing: How do we live
with that fact? Instead of complaining about it…

So, help each other out, don’t distract from the subject all the time?

First I’d like to thank everyone who has tried to help me with my Double
Buffer Trouble, though none of the suggested solutions helped. :wink:

I know now what the problem was/is. I first realised that the reported
timing differences were not due to missed flips but caused by something
else. The extra-long frames did not coincide with the jerks of the
sprite-movement. So I made a simple double-buffered program which moved a
FillRect ‘stripe’ across the screen and sent to a few of my friends and told
them to run it and closely lok for any uneven movement of the stripe (which
was clearly visible on my computer). All of them reported perfectly smooth
movement of the stripe.

This had me convinced that the problem was not in my coding ( a great relief
) or SDL (actually I made a DirectX version too, and it showed the same
jerks) but actually in the hardware or software of my computer.

After reinstalling W2k did not make any difference I installed Windows Me.
It was actually even more jerky in Win Me! Now I was really confused.

Then suddenly it struck me! It must be something to do with my monitor. I
have a TFT-monitor (like the ones on notebook computers) and it does not
work like an ordinary CRT monitor does. Most importantly it does not use an
electron beam for drawing the image on screen. The VBlank is usually the
period when the electron beam moves back to the top of the display to start
drawing the next frame. So TFT’s must simulate this VBlank somehow since
they do not need a VBlank period internally.

Anyway, i tried changing the video refresh rate with my graphics-card
utilities and yes, the flickering changed too. It did not disappear though
but rather got worse as I raised the refresh-rate from 60Hz to 70Hz. But
when I set a custom refresh rate of 62Hz the flickering was almost gone.
This is the setup I use now. The spritemovement still jerks sometimes but
now it’s maybe once every 30 seconds compared to about once a second before.

So it seems that the framerate of the monitor was not exactly the same as
the framerate delivered by the video-card. The monitor’s framerate was
slightly higher which meant that the vide-card would lag more and more
behind the monitor and eventually miss the VBlank period and skip a frame. I
don’t really understand how this can happen but perhaps it is due to some
peculiarity of TFT-monitors, or my monitor in particular. Perhaps it is the
D-A-D conversion that interferes (TFT’s are digital, like the video-card, so
the video-card, thinking the monitor is analog, will convert the signal from
Digital to Analog and send it to the TFT-monitor which wil convert it back
to Digital to display the image…).

Well, I fixed the problem and learned DirectX in the process :). Now I can
get back to my game development.

/Martin._________________________________________________________________
MSN Photos is the easiest way to share and print your photos:
http://photos.msn.com/support/worldwide.aspx

I checked the timing of my code a little closer and I realized that
SDL_Flip() does not really miss a VBlank, it just makes a delay once in
a while. The delay must happen before the flip which is why it’s
visible as jerky framerate. This explains why my loop timings looked
like they did: 16 or 17 ms for most frames (corresponding to my 60Hz
video refresh rate) and once in a ‘slower’ frame immediately followed
by a ‘faster’ one. Like so: …16, 17, 16, 16, 20 (16+4), 12 (16-4),
16, 16, 16…

I noticed that whenever a frame takes longer that 16ms, the next frame
is faster by the same amount. So it would seem the the Flip() return
late from the flip and thus it has to wait less for the next VBlank.
If the Flip was acutally missing VBlank, the ‘slower’ frames should
take twice as long (16.666*2=33ms), and the following frame should not
be affected.

Yeah, you’re right…

BTW, my finding are just about the same: “No” (well, we are talking
about Windows here!) missed retraces, but the timestamps induce some
jitter into the animations.

So what does this behavior suggest?

Windows thinks it’s of no importance that you get woken up right after
each vblank. It “can’t know” that you’re trying to take timestamps. (And
this is despite the fact that it does’t provide any other way of
synchronizing… This is a design flaw that exists in 99% of all drivers
not specifically designed for demanding real time systems.)

Since the effect of these timing
differences is visible on screen the actual buffer-flip must be
delayed.

No - but your timestamps are “wrong”, which (should) affect your
animation.

If your animation just depends on the actual frame rate (say, “move 3
pixels each frame”), now that would be weird…! Are you sure there
isn’t any tearing when this is going on? (Try fast horizontal scrolling…)

And that must mean the the VSync is delayed?! Can this really
be the case?

Well, the actual “sync” might be delayed (or rather, it takes place, and
"a while" later, your thread wakes up), but the retrace isn’t going
anywhere. (Your monitor wouldn’t like that at all…)

I don’t really know the workings of the VSync of the video card so
perhaps the above reasoning is wrong.

Well, the (vertical) retrace is actually the very “command” to the
monitor to move the electron beams back “home” (top-left corner) - and
the monitor electronics depend totally on the timing of this, and the
horizontal retrace/sync pulses to decide which “resolution preset” to use.

The monitor will turn off the output and wait for a few frames to resync
whenever the timing changes significantly, and if not, the picture will
at least “jump” slightly - so it has to be rock solid for things to
work.

I don’t see how a delay in the
flip can cause a delay in the actual screen-output without missing an
entire VBlank period though.

Regardless of how the flip is performed, it will either have to be done
during the retrace (which indeed means that you’ll have to wait another
frame if you miss the retrace), or there will be tearing. As simple as
that.

By the way, I’m getting the SDL list in ‘digest’ format so I can’t
reply to individual postings. How do I make my post stay in thread?

Hmm… No idea. I don’t use threaded view anyway, as it’s just a mess
most of the time. (I browse through everything anyway, so there’s not
much point really - I can just follow the subject lines if I like.)

//Martin, liked the Amiga better…the Copper…sighs deeply

Same here - but it ain’t over yet! :slight_smile:

//David Olofson — Programmer, Reologica Instruments AB

.- M A I A -------------------------------------------------.
| Multimedia Application Integration Architecture |
| A Free/Open Source Plugin API for Professional Multimedia |
----------------------------> http://www.linuxdj.com/maia -' .- David Olofson -------------------------------------------. | Audio Hacker - Open Source Advocate - Singer - Songwriter |-------------------------------------> http://olofson.net -'On Saturday 23 March 2002 00:13, Martin H?ger?s wrote:

My problem is that I can’t get my sprites to move smoothly across the
screen. They move smoothly most of the time but once every second or
so they ‘jerk’, as if a frame was delayed.

Exactly same problem here (Linux, XFree86, Voodoo3, K6-2 500). In all
my programs I make sync that way;

t1=SDL_GetTicks()
t=t0-t1
t0=t1
physics(t)

and animation is “almost smooth”, with “jumps/delays”. Just like you I
checked “t” value and it changes. On faster computer there is no
"jumps/delays" at all.

Ok… How deterministic is your code? That is, is there a chance some
code might occasionally take much longer than “usual” to execute? If so,
you have to be very careful where you read the time, in relation to the
rendering code and the flip.

Of course, on faster machines, the effect of this diminishes as all other
code becomes insignificant in relation to the cost of updating the
screen. (Which is generally limited by the PCI or AGP bus, rather than
the CPU.)

Are you using dynamic memory allocation anywhere in your game loop?

But the most annoying thing is that I can’t see this effect in other
SDL games! lbreakout has smooth animation, no problem with skobo or

This is almost surprizing…! :slight_smile: I can’t remember taking any special
measures in SKobo/Kobo Deluxe - no filters or anything.

OpenGL shooters.

That’s a different story, to some extent - especially if you’re using a
driver with retrace sync. The accelerator command buffer makes things a
lot more asynchronous - which in some cases makes things worse.
Consequently, many OpenGL games use some kind of simple filtering to
infer the actual timing from the (blocking driven) timing of the
rendering loop.

Then again, I’ve had to do this with some drivers, but not with any of
the ones I’ve been using lately. So, in most cases, I’d say it doesn’t
make much of a difference, as long as you’re running at full frame rate.
(It’s the “regular dropped frames patterns” that are nasty, and you don’t
get any of that as long as you do full frame rate…)

I never found any special code in games I’ve checked.

I think it’s about the things you don’t really see, unless you know what
to look for. That is, the order in which things are done, rather than
what is actually done.

And my idea was to calc “mean” of latest “t values”, but I think it
will destroy physics (different game on different computers).

It shouldn’t if you do it right… (Unless your physics engine is broken,
that is - final results should not depend on actual timing in any way -
except that you get them at the right times, of course.)

What filtering will do, more often than not, is make things worse,
especially on slower machines, where you get irregular frame rates. You
need “smarter” filters to deal with that.

Simply put, what you want is not the average frame rate over any period
of time, but rather the most likely instantaneouos frame time. Or
ultimately, the answer to the question:

"When will the frame I'm about to render be displayed?"

Of course, if the driver could answer that question directly, the world
would be a slightly nicer place - but of course, you still have to figure
out whether or not it’s possible to render the next frame in time.
(Because if it takes too long, it will be displayed too late - and at
that point, there’s nothing you can do about it!)

//David Olofson — Programmer, Reologica Instruments AB

.- M A I A -------------------------------------------------.
| Multimedia Application Integration Architecture |
| A Free/Open Source Plugin API for Professional Multimedia |
----------------------------> http://www.linuxdj.com/maia -' .- David Olofson -------------------------------------------. | Audio Hacker - Open Source Advocate - Singer - Songwriter |-------------------------------------> http://olofson.net -'On Saturday 23 March 2002 07:41, Jacek Pop?awski wrote:

On Fri, Mar 22, 2002 at 05:52:40PM +0000, Martin H?ger?s wrote:

Well, I fixed the problem and learned DirectX in the process :). Now I can
get back to my game development.

Wow, I’m glad you figured that out. Good job! :slight_smile:

See ya,
-Sam Lantinga, Software Engineer, Blizzard Entertainment

So, my question is: How do I make SDL_Flip() not miss VBlanks? or,
Why does SDL_Flip() miss VBlank even when it has plenty of time to
wait for it?

This basically sounds like an OS, driver and/or hardware problem - and
I’m afraid there’s nothing much to do about it, short of taking
Linux/lowlatency, hacking the drivers and running your application and
the X server at real time priority.

We are still not focussing on his issue with this answer, though: How
does he make it work with the currently available solutions? No other
kernels/drivers/hacked-solutions will work, because people who download
his ‘game’ will not be able to run it the same way he does. Please
remember we are creating games for people to play, not for some
custom-hacked OS-specific solution…

Right, but at first, the problem seemed to be related to his system,
rather than his program - which doesn’t seem to be the case, though.

You may disregard the rest of that post as speculation based on
insufficient information.

First, kill off any background applications that might want to do
something every now and then. Because you’re basically hogging the CPU
100%, Windows will just stop your process and let the others run until
they block, whenever they wake up. Not even WinNT “real time” priority
will entirely protect you from that, and it seems like Windows is too
stupid to do the right thing regardless of whether retrace sync is
done by busy-waiting or proper (IRQ based) blocking.

It’s not Windows that is stupid here: It is assuming you are waisting
the OS time, and punishes you for that. Windows assumes all
applications should work together, with respect to each other. If you
want a real-time OS, don’t use Windows. Or do not expect that behaviour
from Windows, which would make more sense. Since a lot of people are
using Windows, let’s just keep it at Windows then. And after, that,
respect the shortcomings of the OS, don’t complain about it all the
time, instead try to find a way to live with it. No bashing about it’s
process/thread-priority- handling will help anyone to make smooth
games. A proper solution-suggestion would do better.

I have suggested “proper” solutions as well, but one isn’t supported by
SDL, and probably won’t be any time soon, and all other attempts seem to
be futile here. Neither the OS, nor the theory behind the solution is
wrong - the implementation is.

Another thing you might check is how much of the frame time is used
for rendering. (This includes any “fake” flipping with blits!)

Fake flipping with blits? How does this apply to Windows then… He is
just flipping hardware-wise, no fake or anything like that. This is
Windows… Not some X-bla-bla-Free86-version-6-point-9999 build not
supporting hardware-double-buffering.

So, how would you go about doing h/w pageflipping if the application
requests a bit depth not supported by the video card…?

Besides, AFAIK, XFree86 doesn’t support h/w pageflipping yet, regardless
of build, configuration or version. Nor does Windows in windowed mode.
Likewise for most other targets.

If you’re
using too much, that would explain why even the slightest "hickup"
that delays your game will result in a dropped frame - you simply
can’t render and flip in time, if you’re too late!

Ah, and that’s very true, indeed.

Triple buffering should help a lot, if this is the problem. As an
alternative to hacking a (currently) DirectX specific feature into
SDL, you could try using OpenGL (directly or through glSDL), as that
inherently adds a great deal of extra buffering (ie more “slack”) in
the form of the accelerator command buffer.

Triple buffering will still get you hooked up if you can’t manage to
finish the third buffer in time, although, mathematically seen, this
could only happen twice less times than with double buffering.

That’s not the whole thruth. Triple buffering means that you can actually
use the time you win during one fram, to make up for the extra time you
need for the next frame. This is not possible with less than three
buffers, unless you have significant amounts of non-rendering work to do.

Apart
from that, I would not suggest using OpenGL instead of DirectDraw all
the time: It involves a lot of work, even more than just finding a way
to work with DirectDraw/SDL properly. Also, you are almost suggesting
using OpenGL instead of DirectDraw wouldn’t be that much work, but it
really is.

This is about trying to figure out what’s going on. I’m not seriously
suffesting that anyone should write a 2D game using only OpenGL, unless
the game will make good use of the extra rendering power. Even then, a
software mode is nice, if possible to implement with a reasonable amount
of work.

There are a lot of libraries already written to do this
’2D-in-OpenGL’-wrapping thing, which are far better than SDL, but they
are just not always better, let alone the same. Don’t underestimate
OpenGL, I would say!

Actually, I don’t think there is much point with 2D-on-OpenGL wrappers at
all. Note that glSDL as in implementation of the SDL API on top of
OpenGL, which is quite different. No new API to learn. Eventually, you
won’t even have to recompile SDL 2D code to use OpenGL. That’s the whole
point. If you want more than that, use OpenGL.

If nothing helps, I’m suspecting that your driver is straight polling
the retrace status, which will result in missed retraces if there’s
as much as a kernel driver IRQ in use. You could try to find another
driver and/or video card, that does retrace sync in a more reliable
way… (If the hardware somehow buffers the retrace “event”, it
shouldn’t matter if the driver is a few ms late - the “event” will
still be there for the driver to see. A card with retrace IRQ would
have been just fine - if there were any these days… heh)

Well, I wouldn’t say this is happening on a Windows system, since these
drivers always, currently, deliver rock-solid steady framerates,
without any artifact visible. And again: What is the use of having 1
card that fits your needs, when no one else has that card?

None whatsoever. (Unless you’re building arcade machines, or
something…) That wasn’t the point.

You can code
an application that behaves correctly with your graphics card, but
almost no one else will be able to use it. I do not think that the
original question was how to get smooth-running frames on one set of
hardware, but how to do it on any kind of hardware… So this IRQ
business is not of relevance here, then.

Again, this is just general rambling on what might have been going
wrong in this specific case.

All in all, I understand that some people are frustrated by the
incompatibilities between several hardware-drivers and OS’s, but let’s
please keep that seperate from this mailing list. What I mean is, if
someone asks how to get proper double-buffering work, don’t brag about
how current hardware is non-compliant to some VBlank-IRQ issue or
something like that, but let’s please help this person how to get this
working with the current solutions available. Letting people know you
know your business is fine, but please, let’s keep it short, and
especially, not repeated all the time: We know by now that some OS’s
are not meant for full-screen vsync’ed framerates, let’s focus on the
next big thing: How do we live with that fact? Instead of complaining
about it…

So, help each other out, don’t distract from the subject all the time?

Right, sorry about that.

//David Olofson — Programmer, Reologica Instruments AB

.- M A I A -------------------------------------------------.
| Multimedia Application Integration Architecture |
| A Free/Open Source Plugin API for Professional Multimedia |
----------------------------> http://www.linuxdj.com/maia -' .- David Olofson -------------------------------------------. | Audio Hacker - Open Source Advocate - Singer - Songwriter |-------------------------------------> http://olofson.net -'On Sunday 24 March 2002 06:12, Martijn Melenhorst wrote:

Okay, let’s let this thread rest for a bit, eh? :slight_smile:

See ya,
-Sam Lantinga, Software Engineer, Blizzard Entertainment