Triple buffering

I am currently creating a SDL wrapper for Delphi (and for Kylix after that, don’t worry), especially for creating 2D games, since I just love creating
those, and it’s an easy start. (Well, easy…) Visit the project’s site at http://csdl.sourceforge.net

Anyway, I was following the thread about fixed time steps at http://www.flipcode.com/cgi-bin/msg.cgi?showThread=Tip-
MainLoopTimeSteps&forum=totd&id=-1 while researching the best way to implement my high-res timer, and came to the conclusion that I will not
be able to create screen-refreshrate-independant movement without triple buffering. The SDL_Flip() call forces DirectDraw on Windows to hold
program execution until the next vertical blank, since the WAIT_VBL flag is supplied in the DirectDraw call itself. It should do this, though, since
the flip would otherwise cause a nasty tearing effect. But if the program used triple buffering, the program would not be halted, since it could work
on the third buffer while flipping the second to the primary, if you know what I mean. This is also discussed in the thread I mentioned above.

In short: Either I use 2D-simulation using OpenGL (glSDL sound very interesting, then) or SDL should allow me to do triple buffering when doing 2D.
I’d hate to apply a patch to SDL everytime I update form the CVS tree, so can anyone help me out here?

(Oh, and yes, I do need the doublebuffering since I’m focussing on 8-way scrolling game titles with my class wrapper a lot)

I am currently creating a SDL wrapper for Delphi (and for Kylix after
that, don’t worry), especially for creating 2D games, since I just love
creating those, and it’s an easy start. (Well, easy…) Visit the
project’s site at http://csdl.sourceforge.net

Anyway, I was following the thread about fixed time steps at
http://www.flipcode.com/cgi-bin/msg.cgi?showThread=Tip-
MainLoopTimeSteps&forum=totd&id=-1 while researching the best way to
implement my high-res timer,

Is this a high resolution timer in the sense of something that actually
makes the OS schedule some code to run at regular intervals? (If so,
you’re on the wrong track, IMHO.)

and came to the conclusion that I will not
be able to create screen-refreshrate-independant movement without
triple buffering.

Why? Indeed, triple buffering helps, but double buffering with retrace
sync’ed flipping is sufficient as long as you have enough rendering power.

The SDL_Flip() call forces DirectDraw on Windows to
hold program execution until the next vertical blank, since the
WAIT_VBL flag is supplied in the DirectDraw call itself. It should do
this, though, since the flip would otherwise cause a nasty tearing
effect. But if the program used triple buffering, the program would not
be halted, since it could work on the third buffer while flipping the
second to the primary, if you know what I mean.

Exactly.

This is also discussed
in the thread I mentioned above.

In short: Either I use 2D-simulation using OpenGL (glSDL sound very
interesting, then) or SDL should allow me to do triple buffering when
doing 2D.

Actually, the only reason why OpenGL usually will do what you want with
only double buffering is that virtually every h/w OpenGL implementation
works with a queue of commands that are executed asynchronously in
relation to your application. (This is possible to do with h/w
accelerated 2D as well, but we all know by now that that’s not something
that’s normally available.)

I’d hate to apply a patch to SDL everytime I update form the
CVS tree, so can anyone help me out here?

Well, I don’t really see why there isn’t an SDL_TRIPLEBUFFER flag or
something. It’s not as generic as it should be, but at least, it would
enable some rendering backends to make better use of the available
resources. As far as I can see, it wouldn’t be much work to implement for
DirectDraw, OpenGL and other targets that support it natively.

As to targets that don’t do h/w pageflipping at all, there’s no point in
implementing triple buffering unless you “flip” by blitting
asynchronously using a separate thread on SMP systems, or using busmaster
DMA.

Of course, I could be missing something essential here - wouldn’t be the
first time! :wink:

(Oh, and yes, I do need the doublebuffering since I’m focussing on
8-way scrolling game titles with my class wrapper a lot)

Yeah, I know what you mean. I hate it when you get sore eyes after
playing for ten minutes, because of unsmooth scrolling…

//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 Tuesday 05 March 2002 23:25, Martijn Melenhorst wrote:

I have searched the full archive of this mailinglist for a solution regarding my “Triple Buffer”-quest, and have found the following suggested solution,
called “Semi-Triple Buffering”:

Create a hardware-surface, doublebuffered display
Create a same-size, same-depth software surface

For each game render:
Blit into the software-surface
Blit software-surface to hardware-backbuffer
Call flip() to display hardware-backbuffer

There’s just one ‘but’: the flip() call causes program execution to halt until the next vertical retrace, at least, it does under Win32 using DirectX. So,
this still makes the program stop until the flip has actually begun, right? Since I wanted to use triple-buffering to be able to continue game
execution while waiting for a retrace, this solution does not seem to fit my purposes… Could anyone enlighten me?

Martijn Melenhorst wrote:

I have searched the full archive of this mailinglist for a solution regarding my “Triple Buffer”-quest, and have found the following suggested solution,
called “Semi-Triple Buffering”:

Create a hardware-surface, doublebuffered display
Create a same-size, same-depth software surface

For each game render:
Blit into the software-surface
Blit software-surface to hardware-backbuffer
Call flip() to display hardware-backbuffer

There’s just one ‘but’: the flip() call causes program execution to halt until the next vertical retrace, at least, it does under Win32 using DirectX. So,
this still makes the program stop until the flip has actually begun, right? Since I wanted to use triple-buffering to be able to continue game
execution while waiting for a retrace, this solution does not seem to fit my purposes… Could anyone enlighten me?

Would it be possible to thread this?

If we name the following parts as such:

(1) Blit into the software-surface
(2) Blit software-surface to hardware-backbuffer
(3) Call flip() to display hardware-backbuffer

It is a little hard to explain but you basically need two threads. Parts
1 and 3 can work independantly. You will require some synchronization
for part 2 to occur. That should not be a problem as the thread doing
part 3 will have a short lifetime. It starts up and blocks on completion
of part 2. The other thread does part 1 and when ready does part 2 then
wakes the other thread and goes back to part 1. The other thread wakes
up, does part 3 and then goes back to blocking on completion of part 2.

The advantage of this is that your main thread is not blocking on
anything. The other thread cycles between blocking on the completion of
part 2 and the flip call.

Hi Martijn,
I do realise that you are very keen on using Triple Buffering, but is
it that crucial on modern hardware? Is it really that importent that it
would stop you progressing with your components? You could always
release a Double buffered version first, then as you become more
familiar with SDL you could implement the triple buffering then.
Assuming your classes are set up correctly, this should be transparent
to the user of your components.

Anyway it is just a thought,

L8R,

Dominique.

Martijn Melenhorst wrote:> I have searched the full archive of this mailinglist for a solution regarding my “Triple Buffer”-quest, and have found the following suggested solution,

called “Semi-Triple Buffering”:

Create a hardware-surface, doublebuffered display
Create a same-size, same-depth software surface

For each game render:
Blit into the software-surface
Blit software-surface to hardware-backbuffer
Call flip() to display hardware-backbuffer

There’s just one ‘but’: the flip() call causes program execution to halt until the next vertical retrace, at least, it does under Win32 using DirectX. So,
this still makes the program stop until the flip has actually begun, right? Since I wanted to use triple-buffering to be able to continue game
execution while waiting for a retrace, this solution does not seem to fit my purposes… Could anyone enlighten me?


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

Triple buffering IS very important on modern hardware, since modern hardware PCs run at any refresh-rate resolution. I mentioned this
discussion-thread earlier, http://www.flipcode.com/cgi-bin/msg.cgi?showThread=Tip-MainLoopTimeSteps&forum=totd&id=-1, that really says it
all. (Search for ‘triple’, you’ll see what I mean). It is a really long read, but very, very interesting. Team17 developers are even joining this age-old
discussion :slight_smile:

It is not so much an issue of HOW to do triple buffering, but more of whether it is possible at all with SDL. If it is not possible, I will not be able
to write games that run smooth on all machines/monitors/graphics cards at all, at least, not without a lot of dirty tricks and stuff, so my
component set will not have any proper use at all. So, it is either possible, or I will stop using SDL for my component-set :frowning: I just didn’t think that
the Flip() call would always hold the thread calling it until the next vertical blank, which causes my time-step logics to mess up completely.

As to the other reply about the threads: Is it possible to use SDL_() calls, then, while another thread is waiting for the SDL_Flip() call to
complete? I thought I read something about concurrent threads not being allowed to call SDL_
graphics functions simultaneously? Excuse me,
but I am not that keen with multi-threading, but I WILL implement it if this is the only way to do it.

So: Is a seperate SDL_Flip()-thread a working solution for me???

Hi Martijn,
I do realise that you are very keen on using Triple Buffering, but is
it that crucial on modern hardware? Is it really that importent that it
would stop you progressing with your components? You could always
release a Double buffered version first, then as you become more
familiar with SDL you could implement the triple buffering then.
Assuming your classes are set up correctly, this should be transparent
to the user of your components.

Anyway it is just a thought,

L8R,

Dominique.

Martijn Melenhorst wrote:

I have searched the full archive of this mailinglist for a solution regarding my “Triple Buffer”-quest, and have found the following suggested
solution,

called “Semi-Triple Buffering”:

Create a hardware-surface, doublebuffered display
Create a same-size, same-depth software surface

For each game render:
Blit into the software-surface
Blit software-surface to hardware-backbuffer
Call flip() to display hardware-backbuffer

There’s just one ‘but’: the flip() call causes program execution to halt until the next vertical retrace, at least, it does under Win32 using
DirectX. So,>> this still makes the program stop until the flip has actually begun, right? Since I wanted to use triple-buffering to be able to continue game

execution while waiting for a retrace, this solution does not seem to fit my purposes… Could anyone enlighten me?


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


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

Triple buffering IS very important on modern hardware, since modern
hardware PCs run at any refresh-rate resolution. I mentioned this
discussion-thread earlier,
http://www.flipcode.com/cgi-bin/msg.cgi?showThread=Tip-MainLoopTimeSteps&for
um=totd&id=-1, that really says it
all. (Search for ‘triple’, you’ll see what I mean). It is a really long
read, but very, very interesting. Team17 developers are even joining this
age-old
discussion :slight_smile:

Is the word ‘triple’ in a sub-thread perhaps? Because I can’t find it with
my browser’s Find.

Dirk Gerrits

Try this sub-thread:

http://www.flipcode.com/cgi-bin/msg.cgi?showThread=Tip-MainLoopTimeSteps&forum=totd&id=24>> Triple buffering IS very important on modern hardware, since modern

hardware PCs run at any refresh-rate resolution. I mentioned this

discussion-thread earlier,
http://www.flipcode.com/cgi-bin/msg.cgi?showThread=Tip-MainLoopTimeSteps&for
um=totd&id=-1, that really says it
all. (Search for ‘triple’, you’ll see what I mean). It is a really long
read, but very, very interesting. Team17 developers are even joining this
age-old
discussion :slight_smile:

Is the word ‘triple’ in a sub-thread perhaps? Because I can’t find it with
my browser’s Find.

Dirk Gerrits


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

I have searched the full archive of this mailinglist for a solution
regarding my “Triple Buffer”-quest, and have found the following
suggested solution, called “Semi-Triple Buffering”:

Create a hardware-surface, doublebuffered display
Create a same-size, same-depth software surface

For each game render:
Blit into the software-surface
Blit software-surface to hardware-backbuffer
Call flip() to display hardware-backbuffer

There’s just one ‘but’: the flip() call causes program execution to
halt until the next vertical retrace, at least, it does under Win32
using DirectX.

Well, there has to be a short “halt” every now and then, at least,
unless your rendering time per frame matches the refresh rate exactly.
(Which is unrealistic - unless you’re hacknig a C64 demo. :slight_smile: This is a
result of the very idea with retrace synchronized animation - rendering
exactly one frame per refresh.

So, this still makes the program stop until the flip has
actually begun, right?

What actually should be blocking your thread is not the retrace (or the
"flip") itself, but rather the fact that when you try to lock or blit to
a video buffer, you need to wait until it isn’t used by the video driver
any more. That is, you have to wait until the video driver (or card)
switches to the other buffer. I think DirectX will work that way with
any proper driver.

Since I wanted to use triple-buffering to be
able to continue game execution while waiting for a retrace, this
solution does not seem to fit my purposes… Could anyone enlighten me?

If DirectX uses busmaster DMA to perform the blit from the software
surface to the back buffer, it would be possible to use two software
surfaces (ie quadruple buffering with two h/w and two s/w buffers), so
that you can start rendering another frame while the blit is in progress.

However, the real solution still is real triple buffering with three
h/w buffers (and possibly one or two s/w buffers if you’re doing
significant amounts of s/w blending) - and that has to be implemented in
SDL. (On a per-backend basis, more or less, I’d think.)

//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 Wednesday 06 March 2002 14:52, Martijn Melenhorst wrote:

Martijn Melenhorst wrote:

I have searched the full archive of this mailinglist for a solution
regarding my “Triple Buffer”-quest, and have found the following
suggested solution, called “Semi-Triple Buffering”:

Create a hardware-surface, doublebuffered display
Create a same-size, same-depth software surface

For each game render:
Blit into the software-surface
Blit software-surface to hardware-backbuffer
Call flip() to display hardware-backbuffer

There’s just one ‘but’: the flip() call causes program execution to
halt until the next vertical retrace, at least, it does under Win32
using DirectX. So, this still makes the program stop until the flip
has actually begun, right? Since I wanted to use triple-buffering to
be able to continue game execution while waiting for a retrace, this
solution does not seem to fit my purposes… Could anyone enlighten
me?

Would it be possible to thread this?

If we name the following parts as such:

(1) Blit into the software-surface
(2) Blit software-surface to hardware-backbuffer
(3) Call flip() to display hardware-backbuffer

It is a little hard to explain but you basically need two threads.
Parts 1 and 3 can work independantly. You will require some
synchronization for part 2 to occur. That should not be a problem as
the thread doing part 3 will have a short lifetime. It starts up and
blocks on completion of part 2. The other thread does part 1 and when
ready does part 2 then wakes the other thread and goes back to part 1.
The other thread wakes up, does part 3 and then goes back to blocking
on completion of part 2.

This is efectively a broken software implementation of true triple
buffering. :wink:

What you need is one or more s/w buffers in between the two threads,
arranged as a blocking circular queue. The rendering thread basically
just grabs one buffer at a time, fills it in, and sends it off. When,
eventually, the queue is full, there won’t be any more buffers to render
into, and the rendering thread will have to block until a buffer is
returned from the page flipping thread.

I actually tried to implement this, but there is one major problem with
it: SDL is not thread safe - AFAIK, not even the s/w blitters are. :-/

The advantage of this is that your main thread is not blocking on
anything.

It has to block on something, at least occasionally, to maintain a
steady frame rate - but indeed, it would be great if it didn’t have to
hardsync to a real time event every single frame, the way if
effectively does with normal double buffering.

Double buffering with h/w pageflipping is a thing of the past. Triple
buffering is the way to go. (Unless you have an RTOS and RT video
drivers…)

[…]

//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 08 March 2002 04:25, Adam Gates wrote:

Well, there has to be a short “halt” every now and then, at least,
unless your rendering time per frame matches the refresh rate exactly.
(Which is unrealistic - unless you’re hacknig a C64 demo. :slight_smile: This is a
result of the very idea with retrace synchronized animation - rendering
exactly one frame per refresh.

I understand there should be halt every now and then, but this halt should not stop my program from blitting into the third buffer… see below…

So, this still makes the program stop until the flip has
actually begun, right?

What actually should be blocking your thread is not the retrace (or the
"flip") itself, but rather the fact that when you try to lock or blit to
a video buffer, you need to wait until it isn’t used by the video driver
any more. That is, you have to wait until the video driver (or card)
switches to the other buffer. I think DirectX will work that way with
any proper driver.

That is why I’m using triple buffers: The card is drawing the 2nd buffer to the 1st, that leaves the 3rd open to be played with.
I do not mind waiting for the blit from sw buffer to hw backbuffer to finish, I understand I need to do this, ofcourse. But the wait for the hw
backbuffer to be transferred to the hw frontbuffer is unnecessary as far as I am concerned, since I want to continue drawing in the sw buffer while
this is happening…

I hope this makes it all clear. At this moment I am creating a small test with a Flip semaphore/thread combination, I’ll let y’all know how that
worked out…

You tell’em, dude! :)>On Friday 08 March 2002 04:25, Adam Gates wrote:

Martijn Melenhorst wrote:

I have searched the full archive of this mailinglist for a solution
regarding my “Triple Buffer”-quest, and have found the following
suggested solution, called “Semi-Triple Buffering”:

Create a hardware-surface, doublebuffered display
Create a same-size, same-depth software surface

For each game render:
Blit into the software-surface
Blit software-surface to hardware-backbuffer
Call flip() to display hardware-backbuffer

There’s just one ‘but’: the flip() call causes program execution to
halt until the next vertical retrace, at least, it does under Win32
using DirectX. So, this still makes the program stop until the flip
has actually begun, right? Since I wanted to use triple-buffering to
be able to continue game execution while waiting for a retrace, this
solution does not seem to fit my purposes… Could anyone enlighten
me?

Would it be possible to thread this?

If we name the following parts as such:

(1) Blit into the software-surface
(2) Blit software-surface to hardware-backbuffer
(3) Call flip() to display hardware-backbuffer

It is a little hard to explain but you basically need two threads.
Parts 1 and 3 can work independantly. You will require some
synchronization for part 2 to occur. That should not be a problem as
the thread doing part 3 will have a short lifetime. It starts up and
blocks on completion of part 2. The other thread does part 1 and when
ready does part 2 then wakes the other thread and goes back to part 1.
The other thread wakes up, does part 3 and then goes back to blocking
on completion of part 2.

This is efectively a broken software implementation of true triple
buffering. :wink:

What you need is one or more s/w buffers in between the two threads,
arranged as a blocking circular queue. The rendering thread basically
just grabs one buffer at a time, fills it in, and sends it off. When,
eventually, the queue is full, there won’t be any more buffers to render
into, and the rendering thread will have to block until a buffer is
returned from the page flipping thread.

I actually tried to implement this, but there is one major problem with
it: SDL is not thread safe - AFAIK, not even the s/w blitters are. :-/

The advantage of this is that your main thread is not blocking on
anything.

It has to block on something, at least occasionally, to maintain a
steady frame rate - but indeed, it would be great if it didn’t have to
hardsync to a real time event every single frame, the way if
effectively does with normal double buffering.

Double buffering with h/w pageflipping is a thing of the past. Triple
buffering is the way to go. (Unless you have an RTOS and RT video
drivers…)

[…]

//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 -’


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

Hi Martijn,
I do realise that you are very keen on using Triple Buffering, but
is it that crucial on modern hardware?

In fact, it’s more important now than ever!

If you don’t have triple buffering, you’ll need a real time OS to utilize
all of the CPU power, rather than waiting for the video card to get away
from you next back buffer. Even if you have a real time OS, triple
buffering is good, as it will help handling the fluctuations in per-frame
rendering times that most games will inevitably have.

Is it really that importent that
it would stop you progressing with your components?

Yes, especially since software rendering is too slow for fullscreen
animation in higher resolution, no matter what kind of machine you have.

You could always
release a Double buffered version first, then as you become more

Yeah, especially for games that redram the whole screen every frame, it’s
trivial to change “buffering mode”.

familiar with SDL you could implement the triple buffering then.

This is not possible. It has to be done in the SDL backends - and even
then, it’s not possible on all targets.

Assuming your classes are set up correctly, this should be transparent
to the user of your components.

Yep.

//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 08 March 2002 11:07, Dominique Louis wrote:

Hi David and Martijn

David Olofson wrote:

Double buffering with h/w pageflipping is a thing of the past. Triple
buffering is the way to go. (Unless you have an RTOS and RT video
drivers…)

I have obviously not been keeping up with the latest development in this
area and will now look upon triple buffering as the way to go.

Thanks,

Dominique.
http://www.DelphiGamer.com := for all your Object Pascal game
development needs;
http://www.delphi-jedi.org/Jedi:TEAM_SDL_HOME : Home of JEDI-SDL;
Cross-platform game development with Object Pascal has never been
easier.

[…]

component-set :frowning: I just didn’t think that the Flip() call would always
hold the thread calling it until the next vertical blank, which causes
my time-step logics to mess up completely.

If this is your only problem, you’re doing something wrong. I’ve
suceeded in getting better-than-arcade class smooth scrolling with OpenGL
on a hacked Utah-GLX driver (had to add retrace sync… heh) on Linux,
and that setup doesn’t even do page-flipping! (It renders into a back
buffer, which is then blitted into the front buffer, all in h/w on the
video card.)

The key is to stop whining about not being able to set the refresh rate,
and accept the actual refresh rate as you time base. (You may need a
PLL to extract the actual timing, because of the scheduling timing jitter
of most operating general purpose systems.)

Then, just calculate all your timings from that one way or another. I
prefer running the control system at a predefined, fixed rate, and then
translate the “stream” of coordinates from it into the video frame rate
using interpolation.

Kobo Deluxe does this, but it should be noted that it never makes use of
higer positional accuracy than 1 screen pixel, even when using OpenGL for
rendering.

As to the other reply about the threads: Is it possible to use SDL_*()
calls, then, while another thread is waiting for the SDL_Flip() call to
complete?

Officially, no. SDL is not thread safe.

I thought I read something about concurrent threads not being
allowed to call SDL_* graphics functions simultaneously?

I actually tried using the s/w blitters from one thread, while another
thread was doing partial screen updates, just as a proof-of-concept hack.

I had tiny little pieces all over the place afterwards - as expected.

Excuse me, but
I am not that keen with multi-threading, but I WILL implement it if
this is the only way to do it.

So: Is a seperate SDL_Flip()-thread a working solution for me???

It could work, but the easiest way to do it is probably implementing it
inside SDL, rather than on top of it.

Alternatively, you could use some other s/w rendering library for the
actual rendering, and then use SDL only for the output - or the other way
around.

Anyway, it’s not the proper way of doing triple buffering. Look into
using more than two h/w pages on the targets that support it. (DirectX
does, for example.)

//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 08 March 2002 11:53, Martijn Melenhorst wrote:

Outside of this discussion [which I have been admittedly falling behind
on.] is triple buffering well documented somewhere on the web?

Got any URLs?

DaveOn Friday, March 8, 2002, at 07:47 AM, David Olofson wrote:

On Friday 08 March 2002 11:53, Martijn Melenhorst wrote:
[…]

component-set :frowning: I just didn’t think that the Flip() call would always
hold the thread calling it until the next vertical blank, which causes
my time-step logics to mess up completely.

If this is your only problem, you’re doing something wrong. I’ve
suceeded in getting better-than-arcade class smooth scrolling with
OpenGL
on a hacked Utah-GLX driver (had to add retrace sync… heh) on Linux,
and that setup doesn’t even do page-flipping! (It renders into a back
buffer, which is then blitted into the front buffer, all in h/w on the
video card.)

The key is to stop whining about not being able to set the refresh rate,
and accept the actual refresh rate as you time base. (You may need a
PLL to extract the actual timing, because of the scheduling timing
jitter
of most operating general purpose systems.)

Then, just calculate all your timings from that one way or another. I
prefer running the control system at a predefined, fixed rate, and then
translate the “stream” of coordinates from it into the video frame rate
using interpolation.

Kobo Deluxe does this, but it should be noted that it never makes use of
higer positional accuracy than 1 screen pixel, even when using OpenGL
for
rendering.

As to the other reply about the threads: Is it possible to use SDL_*()
calls, then, while another thread is waiting for the SDL_Flip() call to
complete?

Officially, no. SDL is not thread safe.

I thought I read something about concurrent threads not being
allowed to call SDL_* graphics functions simultaneously?

I actually tried using the s/w blitters from one thread, while another
thread was doing partial screen updates, just as a proof-of-concept
hack.

I had tiny little pieces all over the place afterwards - as expected.

Excuse me, but
I am not that keen with multi-threading, but I WILL implement it if
this is the only way to do it.

So: Is a seperate SDL_Flip()-thread a working solution for me???

It could work, but the easiest way to do it is probably implementing it
inside SDL, rather than on top of it.

Alternatively, you could use some other s/w rendering library for the
actual rendering, and then use SDL only for the output - or the other
way
around.

Anyway, it’s not the proper way of doing triple buffering. Look into
using more than two h/w pages on the targets that support it. (DirectX
does, for example.)

//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 -’


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

There; now we’re getting somewhere! :wink:

Seriously, are there any serious obstacles in the internals of SDL WRT
supporting triple buffering on targets that can do it?

It would just be a new flag, and only a “suggestion”. That is, SDL may
still give you a single + shadow or double buffer screen , if triple
buffering isn’t possible. New applications running on older SDL versions
would simply think that triple buffering isn’t available, so there’s no
binary level API compatibility problem here.

Of course, it would be nice if the new flag is passed on to the resulting
surface, if triple buffering is actually used, so that "smart"
applications that do partial updates can know how many buffers there
actually are.

//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 08 March 2002 14:33, Dominique Louis wrote:

Hi David and Martijn

David Olofson wrote:

Double buffering with h/w pageflipping is a thing of the past. Triple
buffering is the way to go. (Unless you have an RTOS and RT video
drivers…)

I have obviously not been keeping up with the latest development in
this area and will now look upon triple buffering as the way to go.

If this is your only problem, you’re doing something wrong. I’ve
suceeded in getting better-than-arcade class smooth scrolling with OpenGL
on a hacked Utah-GLX driver (had to add retrace sync… heh) on Linux,
and that setup doesn’t even do page-flipping! (It renders into a back
buffer, which is then blitted into the front buffer, all in h/w on the
video card.)

Yep, but OpenGL flips do not wait for the next vertical blank, that is exactly what I want from DirectX using SDL too, but that is just not possible.

The key is to stop whining about not being able to set the refresh rate,
and accept the actual refresh rate as you time base. (You may need a
PLL to extract the actual timing, because of the scheduling timing jitter
of most operating general purpose systems.)

eermm… I am not whining about that at all! I do NOT want to set the refresh-rate of the monitor of the user… I want to be able to let my game run at
a constant rate INDEPENDANT of the refresh rate of the monitor. The whole point of this is, that I have a logic-routine which may only be updated
15 times per second, and an independant drawing routine which may be updated as much as possible. Now, if I have the drawing-routine take too
long since the flip() call has to wait for the next vertical blank, my logic-routine will be delayed because of it. Do you see my point now? I hope it
makes it clear, because I get the impression you are totally misunderstanding my questions regarding this subject.

The MOTD thread I linked to in an earlier post explains exactly what I mean…

If this is your only problem, you’re doing something wrong. I’ve
suceeded in getting better-than-arcade class smooth scrolling with
OpenGL on a hacked Utah-GLX driver (had to add retrace sync… heh)
on Linux, and that setup doesn’t even do page-flipping! (It renders
into a back buffer, which is then blitted into the front buffer, all
in h/w on the video card.)

Yep, but OpenGL flips do not wait for the next vertical blank,

Actually, they do in a sense - but only “in the other end” of the 3D
accelerator command buffer.

that is
exactly what I want from DirectX using SDL too, but that is just not
possible.

Right. That’s why we need triple buffering. Using multiple video buffers
is the s/w rendering equivalent of using a bigger h/w accelerator command
buffer - it just requires h*lluva lot more memory! heh

The key is to stop whining about not being able to set the refresh
rate, and accept the actual refresh rate as you time base. (You may
need a PLL to extract the actual timing, because of the scheduling
timing jitter of most operating general purpose systems.)

eermm… I am not whining about that at all! I do NOT want to set the
refresh-rate of the monitor of the user…

I didn’t mean it like that, and I wasn’t refering to you, but rather
these “I want a fixed frame rate” posts that drop in every now and then.

Sorry if I offended you, or anyone else.

I want to be able to let my
game run at a constant rate INDEPENDANT of the refresh rate of the
monitor.

Then you’ve got the right end of the stick. :slight_smile:

The whole point of this is, that I have a logic-routine which
may only be updated 15 times per second, and an independant drawing
routine which may be updated as much as possible.

With interpolation? Soooo much smoother! :slight_smile:

Now, if I have the
drawing-routine take too long since the flip() call has to wait for the
next vertical blank, my logic-routine will be delayed because of it. Do
you see my point now? I hope it makes it clear, because I get the
impression you are totally misunderstanding my questions regarding this
subject.

Yeah - and although I now have a better idea what the problem is all
about, I still don’t quite understand what exactly you mean by the logic
routine being “delayed”… Isn’t the normal

while(logic_time < next_frame_time)
	run_logic_frame();

solution sufficient?

Note that that means that the logic “frame” function may run anything
from 0 and up times per video frame! Failing to implement that is
probably the most common reason why games fail to run at consistent speed
across systems.

Is the problem that you’re not getting sufficiently accurate timestamps
when checking the time after each flip?

The MOTD thread I linked to in an earlier post explains exactly what I
mean…

Yes, sorry for being lazy - it’s totally clear now.

However, if you want a rock solid solution, well, unsync’ed blit-flips
are problematic, because they cause tearing when used on a single buffer
screen. When used on a h/w pageflipping screen, timing jitter is
introduced, unless there is exactly one blit flip for every real flip.
This would be doable though, and might even solve some problems.

Now, quoting JCAB, here’s the core of the problem:

“Actually, the jittering here happened on a 30 Hz rock-solid framerate.
The problem was that the time spent waiting for the hardware FIFO to
empty would vary every frame, distorting the time measurements.”

That is, even if we are running at a rock solid full frame rate (which
most 2D games will do with glSDL, or other full h/w acceleration
solutions), the problem is that we can’t figure out exactly when each
frame we render will be displayed.

If we indeed do have a constant output frame rate, PLL style filtering of
the timing info derived after flips will work very well. If we end up in
horrendous situations like the 60/30 Hz alteration described earlier in
that thread, any filtering will only make things much worse!

Seems like a way of asking drivers exactly when each frame is flipped in
would help, but there’s actually no generic solution for the alternating
frame rate problem. It could probably be solved in some cases, but not
without close driver/application interaction.

I can’t see how it would be at all possible to do completely in
application space in a reliable way without a RTOS, although using a
separate flipping thread to get closer to the actual h/w flips could help
a lot.

So, are you expecting to get steady full frame rates on any reasonable
hardware…?

//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 08 March 2002 15:11, Martijn Melenhorst wrote:

The whole point of this is, that I have a logic-routine which
may only be updated 15 times per second, and an independant drawing
routine which may be updated as much as possible.

With interpolation? Soooo much smoother! :slight_smile:

Yeah, I’m planning to do simple linear interpolation in my sprite engine… The first game I’ll create with it is a platform game, imagine that: Super Mario jumping interpolated when you’ve got a fast
computer :slight_smile: Smooootthhhh…

Isn’t the normal

while(logic_time < next_frame_time)
run_logic_frame();

solution sufficient?

Let’s say you’re calling run_logic_frame() at a time and the function takes just a little bit too long. This leaves you at, say, 0.001 frametime after a vertical blank, causing the flip() routine to wait
almost a full frame before your application gets control again. So you loose one frame, and worse, your game logic is halted for a full frame! The goal of my solution is to have a fixed-rate
run_logic_frame() call, and a full-frame-rate screen refresh. So you get something like this:

logictime=tick_in_a_second/10; //so, that’s 100 :slight_smile:
oldtime=get_ticks();

while(not gameover)
{
framedrawn=false;
while(flipthread_busy())
{
newtime=get_ticks();
if (newtime-oldtime >= logictime)
{
run_logics(newtime-oldtime);
oldtime=newtime;
}
if ((sw_surface_not_busy) && (not framedrawn))
{
drawframe();
framedrawn = true;
}
}
start_flipthread();
}

flipthread_busy() means that the flipthread is either still blitting the sw surface to the hw backsurface or that the flipthread is waiting for SDL_Flip() to return.

sw_surface_not_busy is a boolean set by the flipthread as soon as the sw surface finished blitting to the hw backsurface.

As you can see, the run_logics() is called 10 times per second, while the frames are being pumped out at (hopefully) full framerate. Two things can happen:

  1. The run_logics() call takes longer than 1/10th of a second: Can be solved by interpreting the supplied time difference and compensating game logics for that.
  2. The drawframe() takes too long: This does not matter much either if the run_logics() implementation does the same as explained in point 1.

If interpolation is used in the drawframe() logics, the game runs smooth on-screen, while the game logics are only updated 10 times a second. And the game can already start drawing a new frame
while the flipthread is still waiting for the next vertical blank!

This is done alot in strategy and RPG games, where the game logics require more lengthy calculations. Since speed is not a real issue in these games, they can just ignore the delivered time
difference in the logics() call mostly. If I’m writing my platform game, on the other hand, I can assume that the run_logics() call will be able to finish in time easily, so I can write the run_logics()
functions as if I were programming a fixed-rate machine (yeah, like the old Amiga days!): The logictime will be 1/50th of a second, so I can code like I was creating a PAL game. Then, to emulate
switching to NTSC, I can make the logictime 1/60th of a second :slight_smile:

Another advantage is that programming for consoles does rely a lot on fixed frame rates. Even Metal Gear Solid 1 was ported to the pc with the principle described above.

However, if you want a rock solid solution, well, unsync’ed blit-flips
are problematic, because they cause tearing when used on a single buffer
screen. When used on a h/w pageflipping screen, timing jitter is
introduced, unless there is exactly one blit flip for every real flip.
This would be doable though, and might even solve some problems.

This is exactly what I’ve got running now: I’m blitting the full software surface to the hardware backbuffer, then my special flip-thread takes care of the flip itself. So, it does wait for a vertical blank
with the flip, but control is returned to the main game thread to continue processing game logics. The next time my program thinks it should do a flip() again, it just looks whether the flip() thread is
still busy, and if not, it starts it again. The advantage is obvious: You get vsync’ed flips which do not interfere with the game logic itself.

So, are you expecting to get steady full frame rates on any reasonable
hardware…?

Yep, I’m aiming high here :slight_smile: The solution I described above could very well solve my problems, but it does require the user to have a quite fast graphics card and good drivers for the sw->hw blits. I
have implemented the thread-solution into CSDL and it seems to work beautifully.

Ofcourse I have to wait with drawing into the software-surface until the sw->hw blit has finished, but that’s easily solved with a mutex inbetween the threads. I could use two software-surfaces,
ofcourse, but I honestly do not think that waiting for that blit will have that much impact, if I’ll have to wait at all, that is.