Allegro.cc - Online Community

Allegro.cc Forums » Game Design & Concepts » Page flipping is slower than double buffer with a powerful graphic card :/

This thread is locked; no one can reply to it. rss feed Print
Page flipping is slower than double buffer with a powerful graphic card :/
kev kev
Member #5,801
May 2005

I created a small pacman-like which running speed is not optimized as well because the engine is based on a 2 dimensions matrix for the level, the drawing of the level and the detection of the collisions are not done at same time so it takes 2x more time that it could take if this was made together.

Anyway it's just a test game that i wrote to improve my allegro skills so i don't really care ^^

My problem is :

I tried 3 video rendering modes : double buffer, page flipping and triple buffer.

I have a good computer (AMD 64 @ 2700 Mhz, 1Go RAM, Nvidia 6800 Ultra) then the page flipping and triple buffer should run faster on it but anyhow it's really slower than with the double buffer :/

So i was wondering if i'm doing something wrong with the last 2 modes.

double buffer code :

1 
2if (set_gfx_mode(GFX_AUTODETECT_WINDOWED,900,650,0,0)){
3 set_gfx_mode(GFX_TEXT,0,0,0,0);
4 allegro_message("graphic mode is not supported");
5 allegro_exit() ;
6 return 1 ;
7 }
8 
9
10
11 BITMAP *page;
12 
13 page = create_bitmap(900, 650);
14 if (!page) {
15 set_gfx_mode(GFX_TEXT,0,0,0,0);
16 allegro_message("Houston we have a problem!");
17 return 1;
18 }
19 
20 
21 while(!key[KEY_ESC]) {
22 
23 
24 clear(page);
25 
26 
27 /* drawing on the page is done here */
28 
29 
30 blit(page,screen,0,0,0,0,SCREEN_W,SCREEN_H);
31 
32 
33 }

triple buffer code :

1 
2if (set_gfx_mode(GFX_AUTODETECT_WINDOWED,900,650,0,0)){
3 set_gfx_mode(GFX_TEXT,0,0,0,0);
4 allegro_message("graphic mode is not supported");
5 allegro_exit() ;
6 return 1 ;
7 }
8 
9
10
11 BITMAP *page[3];
12 
13 int page_active=0;
14 
15 page[0] = create_video_bitmap(900, 650);
16 page[1] = create_video_bitmap(900, 650);
17 page[2] = create_video_bitmap(900, 650);
18 if ((!page[0]) || (!page[1])) {
19 set_gfx_mode(GFX_TEXT,0,0,0,0);
20 allegro_message("Houston we have a problem!");
21 return 1;
22 }
23 
24 
25 while(!key[KEY_ESC]) {
26 
27 
28 clear(page[page_active]);
29 
30 
31 /* drawing on the active_page is done here */
32 
33 
34 show_video_bitmap(page[page_active]);
35 
36 
37 
38 if(page_active == 0) page_active=1;
39
40 else if (page_active == 1) page_active=2;
41
42 else page_active=0;
43 
44 
45 }

(souce code and game avariable here : http://kev060386.free.fr/pacman.rar , 28 kb, free of rights & virus checked )

Thanks for reading my message :)

HoHo
Member #4,534
April 2004
avatar

Of what type are your tiles? Video, system or memory bitmaps?

I'm too lazy to try it out :P

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

kev kev
Member #5,801
May 2005

What do you mean by "tiles" ?

I'm using these sprites for the game :

http://img464.imageshack.us/img464/3810/pacman12br.png

http://img464.imageshack.us/img464/6558/ground7qm.png (for the ground)

http://img464.imageshack.us/img464/5360/block0tz.png

http://img464.imageshack.us/img464/1678/apple7lv.png

I used bmp but when i uploaded them on imageshack it converted it to png :)

HoHo
Member #4,534
April 2004
avatar

I meant in what format are they when you draw them.

I took the time and looked it up from source. It seems like you simply load them with load_bitmap(). That means they are regular memory bitmaps. Drawing these to video bitmap is dead slow compared to drawing one memory bitmap to another or drawing one video bitmap to another.

If you don't target low-end machines (<300MHz) then using only memory bitmaps should give enough speed for most things. Of course you should use double buffering: draw everything to one memory bitmap and blit that to screen once every frame.

If you intend to use all sorts of effects like blending, stretching and rotating then you should probably try out OpenLayer. It is a really nice and simple layer on top of OpenGL and gives you way more speed than Allegro drawing routines, at least until 4.3 gets itself OpenGL driver.

[edit]

If you use regular memory bitmaps then you might consider using RLE sprites. They are generally quite a bit faster than regular bitmaps drawn with draw_sprite. Of course there are some drawbacks like no (simple and relatively fast) way of stretching or rotating.

Also cropping sprites to their minimal size and using an x/y offset to put them to their right position can give you some speedup depending on how much gets cropped. If I remember correctly then grabber tool that comes with Allegro has the function to crop images and it also puts their offsets to the datafile. I used that a couple of years ago and it gave me instant 40% speedup :)

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

Sirocco
Member #88
April 2000
avatar

The interesting thing I've noted over the last few years (and this should really come as no surprise) is that the major bottleneck of unaccelerated 2D graphics is working with the slow-arse video memory. Well, memory clock speeds have hit the freaking stratosphere (comparably) on newer video cards, and this is translating to huge gains for traditional 2D apps. From 1996-2002 I was seeing ~5% performance gain from upgrading my video card, but in the last few years its been closer to 50-100% thanks to the faster memory.

But any way... yes, it's possible to achieve much faster frame rates via double buffering if you don't wait for a vsync call. Page flipping and triple buffering have an element of timing involved that double buffering doesn't necessarily have (and in the case of the code you submitted, definitely does not). That makes all the difference.

-->
Graphic file formats used to fascinate me, but now I find them rather satanic.

kev kev
Member #5,801
May 2005

thanks guys for all your help everything is very interessting ! ;D

I'm not using any image transforming effects or GFX, it's a very basic game ^^

1°) So if i understand well you advice me to create a video bitmap, draw on it and display it with show_video_bitmap() (double buffer) ?

2°) And still if i understand well the fact that page flipping and triple buffering is slower is comming from the vsync thing ?

3°) I'll try the thing about RLE sprites, i didn't hear about it before now so i'll make some search about it thanks :)

4°) Do i need to know something about OpenGL for using OpenLayer ? :)

Sirocco
Member #88
April 2000
avatar

Quote:

2°) And still if i understand well the fact that page flipping and triple buffering is slower is comming from the vsync thing ?

Essentially, yes.

Quote:

3°) I'll try the thing about RLE sprites, i didn't hear about it before now so i'll make some search about it thanks

For your purposes RLE sprites will be overkill -- plus, they lack many of the transformation options that are open to regular bitmap sprites. Remember that RLE sprites are a vestige of Allegro's need to run quickly back when hardware was much less powerful, and as such are useful only in very specific circumstances. I wouldn't recommend bothering with them unless you really need that last bit of 'oomph' out of your program.

-->
Graphic file formats used to fascinate me, but now I find them rather satanic.

Fladimir da Gorf
Member #1,565
October 2001
avatar

Quote:

4°) Do i need to know something about OpenGL for using OpenLayer ?

Nope, that's the idea. It's like if you want to use Allegro you don't need to know DirectX. Check out the manual from my sig ;)

OpenLayer has reached a random SVN version number ;) | Online manual | Installation video!| MSVC projects now possible with cmake | Now alvailable as a Dev-C++ Devpack! (Thanks to Kotori)

kev kev
Member #5,801
May 2005

but is there not a way to desactivate the vsynch for page flipping / triple buffer ? I'm surprised that the double buffer is the fastest graphic mode ???

Quote:

I took the time and looked it up from source. It seems like you simply load them with load_bitmap(). That means they are regular memory bitmaps. Drawing these to video bitmap is dead slow compared to drawing one memory bitmap to another or drawing one video bitmap to another.

Is it possible to load them as video bitmaps ?

Quote:

Nope, that's the idea. It's like if you want to use Allegro you don't need to know DirectX. Check out the manual from my sig

i'll check that out thanks :)

And thanks for the advice sirocco :)

HoHo
Member #4,534
April 2004
avatar

Quote:

For your purposes RLE sprites will be overkill

Perhaps but they are basically just as simple to use as any other allegro bitmap-like structure, except perhaps compiled sprites

Quote:

plus, they lack many of the transformation options that are open to regular bitmap sprites

He did say he doesn't need them. Of course when the need does arise it will take a bit of time to switch over to other methods (~1h for my 80kiB source of Xcom engine but YMMV ;D)

Quote:

I wouldn't recommend bothering with them unless you really need that last bit of 'oomph' out of your program.

Well, that "bit of oomph" is ~40% for my Prescott P4 and for the Xcom engine it was around 30% IIRC. Of course compiled sprites gave me 200%+ speed increase but that is a whole other badly-portable world :-P Also, some relatively simple algorithms gave much bigger gains (I started at around 5FPS on P200 and ended up with 200 on the same machine with the same visuals, P4 had ~5000FPS ;D).
It is fun to play around with all those different bitmap types but it can waste a lot of time that you could have used elsewhere.

In general I would suggest using OpenLayer. I think it is much simpler to use than allegro because you don't have to worry about all those different bitmap and rendering settings. Also you get most nice effects basically for free.

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

ReyBrujo
Moderator
January 2001
avatar

Quote:

but is there not a way to desactivate the vsynch for page flipping / triple buffer ? I'm surprised that the double buffer is the fastest graphic mode

According to the manual:

Quote:

Allegro will handle any necessary vertical retrace synchronisation when page flipping, so you don't need to call vsync() before it. This means that show_video_bitmap() has the same time delay effects as vsync() by default. This can be adjusted with the "disable_vsync" config key in the [graphics] section of allegro.cfg.

--
RB
光子「あたしただ…奪う側に回ろうと思っただけよ」
Mitsuko's last words, Battle Royale

ImLeftFooted
Member #3,935
October 2003
avatar

Quote:

2°) And still if i understand well the fact that page flipping and triple buffering is slower is comming from the vsync thing ?

You kidding? triple buffering you don't have to wait around for the vsync. Anyway, what you're really doing is page flipping with 3 pages, which isnt triple buffering. Anyway, before you can do anything with page flipping or triple buffering you have to check gfx_capabilities.

Ok, so to understand if page flipping will be faster for you you have to understand the relationship between the graphics card and the CPU. The CPU sends pictures through the 'bus' to the graphics card. Now that is slow. The graphics card can also send picutres back through the 'bus' to the CPU. Thats even slower, don't do that.

So, there a few allegro routines that require reading from the desination picture. One of these routines is blending. If you blend something with the screen image it will have to read in the pixels that are on the screen, which is slow and bad. don't do it.

Anyway, I'm just babbling on at this point. I'll get to the point.

So, to do triple buffering:

if(!(gfx_capabilities & GFX_CAN_TRIPLE_BUFFER))
    enable_triple_buffer();

if(gfx_capabilities & GFX_CAN_TRIPLE_BUFFER)
    pagecount = 3;
else
    pagecount = 2;

So here we check if gfx_capabilities can do triple buffering, if not we try to cheat and see if we can enable it. If that works we set pagecount to 3, which means we're going to do triple buffering. If it doesnt we set it to 2 which means we're going to do page flipping.

ok, so since you already get page flipping, im just going to explain how to do triple buffering:

1BITMAP *destination;
2 
3... init code ...
4 
5while(!quit) {
6 
7 while(poll_scroll())
8 rest(0);
9
10 page = ++page % pagecount;
11
12 if(request_video_bitmap(pages[page]) != 0)
13 shit("Shit! we're fucked. Time to quit the program.");
14
15 destination = pages[(page + 1) % pagecount];
16 
17 ...
18 
19 do_all_drawing_here(destination);
20 
21 ...
22}

request_video_bitmap returns immediately. Use poll_scroll to check when the BITMAP has been successfully moved to center-screen. We do rest(0) while checking poll_scroll so we don't waste CPU cycles.

Next we advance the page variable, wrapping back to 0 if we've gone over pagecount.

Next we request that the given page is moved center-screen.

Then we set the destination bitmap (the bitmap that should be drawn to) to the next page in the list (again wrapping down to 0 if the page is bigger then pagecount).

Neil Walker
Member #210
April 2000
avatar

Quote:

but is there not a way to desactivate the vsynch for page flipping / triple buffer ? I'm surprised that the double buffer is the fastest graphic mode

There is a way to deactive the vsync, check the manual, but doing so is silly. But double buffering is only faster only because you are that you are blitting video bitmaps onto memory. If you are using paging/triple buffering then you need to, for each bitmap you load:

a) load your bitmap into memory
b) create a video bitmap of the same size
c) blit it onto the video bitmap
d) destroy your original loaded bitmap

the vsyncing is there for a very good reason, and that is to avoid tearing and give a rock solid smoothness to your game. There is no point in having a FPS greater than the refresh of your monitor as it does nothing.

For the benefit of Windows users, if you are thinking of just using double buffering/memory bitmaps, create system bitmaps instead. There are no drawbacks.

Triple buffering, btw, only works on fullscreen (windows anyway).

One thing I discovered (and it could just be me) is when I do VRAM->RAM blits my FPS exactly halves. I wonder if the video card is locking something the first pass and drawing the second.

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

kev kev
Member #5,801
May 2005

In fact from the beginning i thought my game was too slow with double buffer and even more slower with page flipping / triple buffering but i was wrong !!

I coded a small fps counter and here is what i get :

- 180 / 195 fps with double buffer windowed (memory images -> memory buffer -> screen)

- impossible to run fps with double buffer windowed (video images -> video buffer -> screen), see below

- 59 constant fps with page flipping windowed (memory images -> video buffer -> screen)

- 59 constant fps with page flipping windowed (video images -> video buffer -> screen)

- 58 / 59 fps with triple buffer fullscreen (memory images -> video buffer -> screen)

- 58 / 59 fps with triple buffer fullscreen (video images -> video buffer -> screen)

=> clearly the game is too lite to make my computer lag, it'd be interesting if someone could test the different modes on a PII or something like that so we can see if it's really changing the fps rate ;)

Otherwise i have to find a way to greatly increase the load of the game on the computer but i don't know any efficient way to do that :/

I made a small package for testing all the modes if you want to try it :

http://kev060386.free.fr/test.rar (virus checked)

I tried Neil's method, double buffer with video memory but when i use it my whole computer is lagging like hell, i guess the frame rate is way too high, which is strange because show_video_bitmap() should limitate it with the vsync thing :o

1 BITMAP *page, *sprite, *temp;
2
3 page=create_video_bitmap(ECRAN_X,ECRAN_Y);
4
5 temp=load_bitmap("pacman1.bmp",NULL);
6 sprite=create_video_bitmap(temp->w,temp->h);
7 blit(temp,sprite,0,0,0,0,temp->w,temp->h);
8
9 int x,y;
10
11 x=y=50;
12 
13
14 while (!key[KEY_ESC]){
15
16 clear(page);
17
18 draw_sprite(page,sprite,x,y);
19
20 if(key[KEY_RIGHT]) x=x+1;
21
22
23 show_video_bitmap(page);
24 
25 
26 }

I didn't have time to test OpenLayer but i'll do it when i have.

Thanks again for the help :)

Neil Walker
Member #210
April 2000
avatar

If you want to do some more exhaustive tests, download my project (from my sig) and play with the animation example 3 or 4. All the configurations for the permutations of double, triple, paging, system, memory, fullscreen, windowed, vsync, etc. are available by simply modifying the two xml files and you can see the FPS that you get.

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Arthur Kalliokoski
Second in Command
February 2005
avatar

Double buffering is just to hide the intermediate stages of drawing. Blitting one image to screen once isn't nearly as noticable.

If you were to draw a single vertical line in your buffer, and move it to one side as you blit it to the screen, you'd notice it has a "break" in it where the blit overtook the scanline that the monitor was refreshing at the time. Vsync is to get them to start at the same time, so the blit will outrun the update on screen and not get that torn look.

Vsync also makes your program wait until the monitor/card sends the electron beam back to the top of the screen, so if your program has a lot of stuff to do it'll be even slower having to stop every now & then. Kind of like if you were an overworked sign painter, and only had one easel, you'd have to wait until a customer picked up his sign before you could start on the next sign to paint. If you had a huge backlog of work this'd be murder on your progress.

The idea of triple buffering is to allow your program to proceed with the SECOND frame ahead of what's displayed, kind of like if you were a sign painter, you could set one sign off to the side until the customer picked it up, and started painting a whole new sign. Only if you had two completed signs would you have to sit doing nothing.

I'm not sure, but I think some games have a WHOLE LOT of predrawn frames "waiting in the wings", I seem to remember a note in Max Payne about how to turn this off if you have a slow computer (so your keys would be more responsive)

They all watch too much MSNBC... they get ideas.

ImLeftFooted
Member #3,935
October 2003
avatar

Quote:

- 59 constant fps with page flipping windowed (memory images -> video buffer -> screen)

- 59 constant fps with page flipping windowed (video images -> video buffer -> screen)

- 58 / 59 fps with triple buffer fullscreen (memory images -> video buffer -> screen)

- 58 / 59 fps with triple buffer fullscreen (video images -> video buffer -> screen)

The page flipping results look about right. You cant go faster then the update rate of your monitor when you do page flipping (looks like your monitor is 60 hz).

Now triple buffering should be faster then double buffer. But as i mentioned earlier you aren't actually doing triple buffering. You're doing page flipping with 3 pages. That is not triple buffering.

kev kev
Member #5,801
May 2005

I tried to use your triple buffering method to run the test but it didn't work :/

I tried this instead :

1 
2 while(!key[KEY_ESC]) {
3 
4 clear(page[page_active]);
5 
6 /* drawing is done here */
7 
8 while(poll_scroll())rest(0);
9
10 request_video_bitmap(page[page_active]);
11 
12 
13 if(page_active == 0) page_active=1;
14
15 else if (page_active ==1) page_active=2;
16
17 else page_active=0;
18 
19 
20 }

Is it wrong ? ;D

I attached full source code with fps display, use key 'r' and 'e' to increase / decrease the number of sprites displayed and see the result on your fps :)

ImLeftFooted
Member #3,935
October 2003
avatar

Quote:

Is it wrong ? ;D

Yeah, you have to check gfx_capabilities and report an error message if triple buffering is not set. You also must check the return value of request_video_bitmap and display an error if that fails.

Other then that, yes, you have the idea correct. One undocumented little thing about allegro: the last 2 parameters of set_gfx_mode. On some OSs (namely windows) these two parameters must be set to 3* the screen size to have triple buffering. On other OSs, they must both be 0.

Anyway, triple buffering is a pita to do right. You have to check the return values of stuff. For all you know request_video_bitmap is just failing over and over and your test is meaningless.

kev kev
Member #5,801
May 2005

Right i did it ;)

It's still slower than double buffer so i guess i'll use the double buffer display mode and i'll try allegroGL later so i can see what is the best for my games ( because i'm not allowed to use C++ then openlayer in my project)

Thanks a lot for all your help :)

Tobias Dammers
Member #2,604
August 2002
avatar

Frame rate is BS. As long as it is as high as your vsync rate, you're good.
What you really want to know is: How long does rendering a frame take?
Displaying 5000 frames per second doesn't look any different from displaying 60 frames per second (at least when your screen is set to 60 Hz). Page flipping will max at 60 fps in this scenario, but a double buffering algo that renders 1000 fps won't look any smoother. If, however, you clock your drawing routine (drawing to the back buffer, that is), without the actual flip (which is negligible anyway), this tells you exactly if your optimization attempts were successful.
You might want to calculate a theoretical maximum frame rate (1 / frame render time), so that the number becomes more intuitive. But even if that number is 5000, you won't see more frames per second than your monitor allows. Every extra frame you render is wasted cpu/gpu time.

There is another reason why page flipping may be slower. If you do a lot of blending (without acceleration), this means a lot of data is read back from the back buffer; with page flipping, this requires pumping data back from the vram to ram, which is quite slow. Remember, the video bus is often the bottleneck in the rendering chain! Similarly, a lot of overdraw requires more data to be pumped to the graphics card than with a single double buffer blit, which may also slow the whole system down. Also, keeping sprites in vram can help, as others pointed out, since you only need to upload them once instead of every time you draw them. This of course doesn't make sense for a (system ram) double buffer; for that, keep sprites in system RAM.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

ImLeftFooted
Member #3,935
October 2003
avatar

Oh right yeah i wa wrong with my calculations. Basically your program is spending most of its time in this loop (talking about triple buffer here):

while(poll_scroll())rest(0);

Whats cool about triple buffering is that you can transfer the time the CPU spends in that loop to your code. In page flipping you can only do 50 iterations of logic a second, but with triple buffering you can do as much as you want.

So to summeraize and be more clear: Triple Buffering will lock you into 60 fps (given a monitor thats set at 60hz). This is expected and doesnt matter a bit. If the number gets higher then that your code has bugs in it.

Evert
Member #794
November 2000
avatar

Quote:

In page flipping you can only do 50 iterations of logic a second

Huh?

Tobias Dammers
Member #2,604
August 2002
avatar

Dustin: The main benefit of triple buffering is that you don't need to wait for a vertical retrace before sending data to the graphics hardware.
In page flipping, you would do:
1. Execute logic (as many times as you want)
2. Render a frame
3. Wait for vsync
4. Flip

Triple buffering would do:
1. Execute logic (as many times as you want), until a flip has occurred
2. Render a frame
3. Flip

In both cases, you use a timer to control the logic update rate. The difference is that in page-flipping, your program does nothing while waiting for vsync, while in triple buffering mode, you store the next frame in an extra buffer, and the OS and hardware will display it as soon as a retrace happens, while your program continues execution.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

Go to: