Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Speed issues with Allegro 5.0.4

Credits go to kenmasters1976 for helping out!
This thread is locked; no one can reply to it. rss feed Print
Speed issues with Allegro 5.0.4
Hepolite
Member #13,716
November 2011

I am having some issues with Allegro that I simply can't figure out how to solve myself, after spending some time searching for an answer I still haven't found anything that I could use.

I am new to Allegro, so there's much I don't know yet, so please don't hate me for this question. :)
I have, however, spent some time with C++ so I know how to do some things, but I'm far, far from an expert.

I'm trying to make a program that I will eventually expand to a game, but for now I'm working on a level editor, and I've managed to set up a decent interface and the GUI is working as I want it to. Everything works just as I expected - just tens if not hundreds of times slower... I have noticed that my simple GUI renders at about 20-30 FPS, which is just ridiculously slow. However, as soon as I take out the drawing part from my main loop, the program runs much faster, I'd estimate much more than 1000 FPS. Just a very rough guess as the program seems to run 960 frames in less than a second.

I have no idea what I can do to fix this...
I'm using Microsoft Visual C++ 2010 and Allegro 5.0.4, and this is some parts of the code I use to draw everything:

Setting up Allegro:

#SelectExpand
1bool gfx_init(void) 2{ 3 // Error-checking 4 bool noerror = true; 5 6 // Starting Allegro 7 if (!al_init()) 8 { 9 al_show_native_message_box(NULL, "", "", "Failed to initialize Allegro!", NULL, NULL); 10 noerror = false; 11 } 12 13 if (noerror) // Setting up the screen 14 window_set_size(640, 480); 15 16 if (!al_init_image_addon()) 17 { 18 al_show_native_message_box(NULL, "", "", "Failed to initialize Allegro image!", NULL, NULL); 19 noerror = false; 20 } 21 22 al_init_font_addon(); 23 if (!al_init_ttf_addon()) 24 { 25 al_show_native_message_box(NULL, "", "", "Failed to initialize Allegro TTF!", NULL, NULL); 26 noerror = false; 27 } 28 29 if (!al_install_keyboard()) 30 { 31 al_show_native_message_box(NULL, "", "", "Failed to initialize Allegro keyboard!", NULL, NULL); 32 noerror = false; 33 } 34 if (!al_install_mouse()) 35 { 36 al_show_native_message_box(NULL, "", "", "Failed to initialize Allegro mouse!", NULL, NULL); 37 noerror = false; 38 } 39 if (!al_install_joystick()) 40 { 41 al_show_native_message_box(NULL, "", "", "Failed to initialize Allegro joystick!", NULL, NULL); 42 noerror = false; 43 } 44 45 // Handle other things related to Allegro 46 if (noerror) 47 { 48 // Set the bitmaps to video memory 49 al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP); 50 } 51 52 // Return 53 return noerror; 54}

Setting up a display

#SelectExpand
1void window_set_size(int width, int height) 2{ 3 // Set the new width/height 4 screen_width = width; 5 screen_height = height; 6 7 // Reset the screen 8 if (screen != NULL) 9 al_destroy_display(screen); // Todo: Move the window to center of screen after resizing it. This line will be removed later... 10 //al_resize_display(screen, window_get_width(), window_get_height()); 11 //else 12 screen = al_create_display(window_get_width(), window_get_height()); 13 14 if (!screen) 15 al_show_native_message_box(NULL, "", "", "Failed to set up a screen!", NULL, NULL); 16 17 if (buffer != NULL) 18 al_destroy_bitmap(buffer); 19 buffer = al_create_bitmap(window_get_width(), window_get_height()); 20}

Main loop drawing

#SelectExpand
1// Process draw event 2 surface_reset_target(); // Make sure that the surface gets reset, may cause unwanted problems if it isn't 3 for (i=0; i<viewport_count; i++) 4 { 5 // Get viewport 6 viewport_current = (s_viewport*)list_find_value(viewport_list, i); 7 current = viewport_get_surface(viewport_current); 8 al_set_target_bitmap(current); 9 10 // Clear viewport to black 11 al_clear_to_color(viewport_current->color); 12 13 // Draw objects to viewport 14 node = object_list->start; 15 while (node != NULL) 16 { 17 object = (c_base*)node->data; 18 node = node->next; 19 object->event_draw(); 20 } 21 } 22 23 24 // Draw buffer to screen and update screen 25 surface_reset_target(); 26 27 for (i=0; i<viewport_count; i++) 28 { 29 // Obtain viewport bitmap 30 viewport_current = (s_viewport*)list_find_value(viewport_list, i); 31 current = viewport_get_surface(viewport_current); 32 33 // Draw viewports to screen 34 draw_bitmap(current, viewport_current->port->x, viewport_current->port->y, 0,0, 35 viewport_current->port->w/viewport_current->view->w, viewport_current->port->h/viewport_current->view->h, 36 0); 37 } 38 al_flip_display(); // Update screen

Drawing bitmaps:

#SelectExpand
1void draw_bitmap(ALLEGRO_BITMAP *bitmap, float x, float y, float offx, float offy, float scalex, float scaley, float angle) 2{ 3 if (bitmap == NULL) // Can't draw an invalid bitmap 4 return; 5 6 // Actual drawing 7 if (angle == 0) 8 { 9 if (scalex == 1 && scaley == 1) 10 al_draw_bitmap(bitmap, x-offx, y-offy, NULL); 11 else 12 { 13 float w = al_get_bitmap_width(bitmap); 14 float h = al_get_bitmap_height(bitmap); 15 al_draw_scaled_bitmap(bitmap, 0, 0, w, h, x-offx, y-offy, w*scalex, h*scaley, NULL); 16 } 17 } 18 else 19 { 20 if (scalex == 1 && scaley == 1) 21 al_draw_rotated_bitmap(bitmap, offx, offy, x, y, angle*ANGLE_TO_RAD, NULL); 22 else 23 al_draw_scaled_rotated_bitmap(bitmap, offx, offy, x, y, scalex, scaley, angle*ANGLE_TO_RAD, NULL); 24 } 25}

Other details:
The surfaces aren't anything else than allegro bitmaps with a different name, so surface_reset_target() simply means al_set_target_backbuffer(screen). surface_set_target is just the same as al_set_target_bitmap, just with a little bit more code related to my engine.

I really hope that anyone can help me out with this. I really do want to make a game with C++, which is something I've never been able to do before. But I can't because my program is running so slow that it hurts...

This is what I'm drawing thus far:
http://i43.tinypic.com/2mwf8xz.png
There's no reason it should draw as slow as it's doing...

EDIT:
After running some tests, I notice that most of the slowdown seems to come from the al_flip_display() call. Running 960 cycles with everything but that lines seems to take just around 5 seconds which I might be able to live with, but with that line... Oh boy, soooo slow.

Matthew Leverton
Supreme Loser
January 1999
avatar

First, are you loading all of your fonts and bitmaps after creating a display? This also means reloading them if you change displays.

Second, why are you creating a full screen buffer? That's usually not necessary on Allegro 5. Just draw to the back buffer and then flip it. No need to have another buffer on top of that.

Disclaimer: I only quickly scanned your code.

Hepolite
Member #13,716
November 2011

Okay, I tried to shift around the order the code executes.
Now resources load before the display is created. It looks like that caused even more issues, as now the program runs even slower, about ten-fifteen seconds per frame. Seconds per frame, not frames per second :/

About the buffer... It's being created/destroyed in the code, but I don't use it. I have simply forgotten to remove it, so that's not the problem either.

The order would now be as following:
Init Allegro
Init addons
Init display
Init resources
Main loop:
- Process logic
- Process drawing
Free resources
Free Allegro

Matthew Leverton
Supreme Loser
January 1999
avatar

Hepolite said:

Now resources load before the display is created.

I didn't ask you to do that... You want to load resources after creating the display.

Hepolite
Member #13,716
November 2011

No problem with that, fixed the order back to what it was right after testing that. But nontheless, the speed issue does remain, and I have no idea what I can do to solve that.

kenmasters1976
Member #8,794
July 2007

Try moving also the addons initialization and place them after creating the display and see if that helps. Also, keep in mind that drawing to anything other than the backbuffer can be really slow on some older cards, so if your current target is not the backbuffer, it can be the cause.

Hepolite
Member #13,716
November 2011

Creating the display before the addons does squeeze a few more FPS out of this, but it's still running slow. I've added a special case when there's zero viewports, so the engine uses the backbuffer directly. But what if I really need two viewports at the same time? I would have to render everything separately to each of those viewports (The drawing can be different depending on the viewport, say you don't want to render something to the second viewport, but only the first), then combine them to the backbuffer, how could that be optimized?

But still, this program is still running too slow, even when rendering directly to the backbuffer, without the other targets. Is there anything else I can do to speed this up? I'm willing to send the whole project over to do so, if that is what it takes to solve this.

kenmasters1976
Member #8,794
July 2007

Hepolite said:

But what if I really need two viewports at the same time?

Maybe you could try tweaking the clipping rectangle on the backbuffer. Anyway, it shouldn't be so slow when you draw directly to the backbuffer so there must be something else causing the slowdown.

Are you using Direct3D or OpenGL? try with both and see if there's any difference.

tobing
Member #5,213
November 2004
avatar

Are your surfaces also video bitmaps? Because if they're memory bitmaps, that may explain why it's slow.
Just an idea.

Hepolite
Member #13,716
November 2011

Are you using Direct3D or OpenGL? try with both and see if there's any difference.

Well, I don't really know how to change to those. Any pointers would be helpful.

Also, about the backbuffer, would that work even if I want to draw one thing to the first viewport, but not the other, or the other way around? Also, there's some cases where I really have to use surfaces, I can't cheat that by using the backbuffer, can I? Besides, sounds like this will grossly over-complicate everything...

Well, I do have a
al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
before the surfaces are created, well, right after the addons has been initialized, actually. So they should be video bitmaps, right?

As I said, I'm willing to share the entire source code if is required to solve this issue.

kenmasters1976
Member #8,794
July 2007

If you're using Windows then you're using Direct3D as it's the default on Windows. Try adding al_set_new_display_flags(ALLEGRO_OPENGL); before the display creation and see whether it runs better or not.

It's true that using the backbuffer for everything could complicate things and it probably isn't necessary on recent graphics cards. What's your graphics card? and do you have the latest drivers for it?.

Hepolite
Member #13,716
November 2011

Try adding al_set_new_display_flags(ALLEGRO_OPENGL); before the display creation and see whether it runs better or not.

Ah, thanks! That did the trick, got about 100 FPS but now it's stable even when drawing to the surfaces, and when drawing hundreds of objects at the same time.

Though things are running slow with 4000+ objects, but I doubt that that is Allegro's fault :)

Elias
Member #358
May 2000

Isn't Direct3D supposed to sometimes work better (and in general not worse)? (And that being the reason we even support it?)

--
"Either help out or stop whining" - Evert

Matthew Leverton
Supreme Loser
January 1999
avatar

Elias said:

Isn't Direct3D supposed to sometimes work better (and in general not worse)?

It probably depends on the quality of the Allegro code.

Also, I think there's a much greater chance of OpenGL being totally broken on a Windows computer than the D3D drivers.

Go to: