|
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'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... Setting up Allegro: 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 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 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: 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: 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: EDIT: |
Matthew Leverton
Supreme Loser
January 1999
|
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. 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: |
Matthew Leverton
Supreme Loser
January 1999
|
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
|
Are your surfaces also video bitmaps? Because if they're memory bitmaps, that may explain why it's slow. |
Hepolite
Member #13,716
November 2011
|
kenmasters1976 said: 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 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
|
kenmasters1976 said: 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?) -- |
Matthew Leverton
Supreme Loser
January 1999
|
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. |
|