Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » One function call cuts my FPS in half

This thread is locked; no one can reply to it. rss feed Print
One function call cuts my FPS in half
sadelbrid
Member #15,200
June 2013

I am trying to narrow down why my fps is so low. After messing around, I found that my fps drops in half when calling a function. I then went into that function and commented out everything and kept rerunning my program while putting back each line one at a time. Everything was running at 60 fps... until I added one drawing function:

al_draw_bitmap_region(player.graphic, 0, player.direction, 26, 26, player.x - 13, player.y - 13, NULL);

This is just a 26x104 bitmap of my player sprite. This drawing function cuts my fps from 60 to 30. However the fps doesn't drop when I draw a primitive instead. Any thoughts?

Edgar Reynaldo
Member #8,592
May 2007
avatar

sadelbrid
Member #15,200
June 2013

I create my display before anything else. I pulled the player sprite graphic out of the player struct and declared it in my main function. As expected, that didn't change anything.

SiegeLord
Member #7,827
October 2006
avatar

To be 100% sure it's not a memory bitmap, try calling al_get_bitmap_flags(player.graphic) & ALLEGRO_VIDEO_BITMAP and making sure that's not zero.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

sadelbrid
Member #15,200
June 2013

Calling al_get_bitmap_flags(playerSprite) & ALLEGRO_VIDEO_BITMAP returned 1. If that is how you check, it seems that it isn't a memory bitmap. To be sure, I called al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP) at the beginning of my program.

Gideon Weems
Member #3,925
October 2003

Are you vsyncing? The draw operation could just be the straw that breaks the camel's back.

Edgar Reynaldo
Member #8,592
May 2007
avatar

sadelbrid
Member #15,200
June 2013

Here is my declaration and my gameloop

#SelectExpand
1al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP); 2//... 3ALLEGRO_BITMAP *playerSprite = al_load_bitmap("player.png"); 4//... 5while(!done) 6 { 7 ALLEGRO_EVENT ev; 8 al_wait_for_event(queue, &ev); 9 if(ev.type == ALLEGRO_EVENT_TIMER) 10 { 11 if(ev.timer.source == mainTimer) 12 { 13 draw = true; 14 if(inputs[W]){player.y -= player.speed; player.direction = UP; player.imageX -= 32;} 15 else if(inputs[S]){player.y += player.speed; player.direction = DOWN; player.imageX -= 32;} 16 else if(inputs[A]){player.x -= player.speed; player.direction = LEFT; player.imageX -= 32;} 17 else if(inputs[D]){player.x += player.speed; player.direction = RIGHT; player.imageX -= 32;} 18 19 20 if(player.imageX < 0){player.imageX = 64;} 21 22 //Bounds checking 23 if (player.x > al_get_bitmap_width(environment)){player.x = al_get_bitmap_width(environment);} 24 else if (player.x < 0){player.x = 0;} 25 if (player.y < 0){player.y = 0;} 26 else if (player.y > al_get_bitmap_height(environment)){player. y = al_get_bitmap_height(environment);} 27 28 HitDetect(player); 29 cloud1x -= 1; 30 cloud2x -= 1; 31 if(cloud1x < -4000){cloud1x = 4000;} 32 if(cloud2x < -4000){cloud2x = 4000;} 33 } 34 35 else if (ev.timer.source == waterTimer) 36 { 37 waterdraw = true; 38 waterUpdateNeeded = true; 39 waterX += 32; 40 if (waterX > 96){waterX = 0;} 41 } 42 } 43 44 else if (ev.type == ALLEGRO_EVENT_KEY_DOWN) 45 { 46 switch (ev.keyboard.keycode) 47 { 48 case ALLEGRO_KEY_W: 49 inputs[W] = true; 50 break; 51 case ALLEGRO_KEY_S: 52 inputs[S] = true; 53 break; 54 case ALLEGRO_KEY_A: 55 inputs[A] = true; 56 break; 57 case ALLEGRO_KEY_D: 58 inputs[D] = true; 59 break; 60 case ALLEGRO_KEY_SPACE: 61 inputs[SPACE] = true; 62 break; 63 case ALLEGRO_KEY_I: 64 inputs[I] = true; 65 inventoryon = !inventoryon; 66 67 break; 68 case ALLEGRO_KEY_ESCAPE: 69 done = true; 70 break; 71 } 72 } 73 else if (ev.type == ALLEGRO_EVENT_KEY_UP) 74 { 75 switch (ev.keyboard.keycode) 76 { 77 case ALLEGRO_KEY_W: 78 inputs[W] = false; 79 break; 80 case ALLEGRO_KEY_S: 81 inputs[S] = false; 82 break; 83 case ALLEGRO_KEY_A: 84 inputs[A] = false; 85 break; 86 case ALLEGRO_KEY_D: 87 inputs[D] = false; 88 break; 89 case ALLEGRO_KEY_SPACE: 90 inputs[SPACE] = false; 91 break; 92 case ALLEGRO_KEY_I: 93 inputs[I] = false; 94 break; 95 } 96 } 97 98 else if (ev.type == ALLEGRO_EVENT_MOUSE_AXES) 99 { 100 maincurser.x = ev.mouse.x; 101 maincurser.y = ev.mouse.y; 102 } 103 104 else if (ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) 105 { 106 107 } 108 109 if(draw && al_is_event_queue_empty(queue)) 110 { 111 //-------------------FPS-------------------------- 112 double game_time = al_get_time(); 113 if(game_time - old_time >= 1.0) 114 { 115 fps = frames_done / (game_time - old_time); 116 frames_done = 0; old_time = game_time; 117 } 118 frames_done++; 119 cout << fps << endl; 120 //-------------------------------------------------- 121 draw = false; 122 //Redraw 123 RedrawEnvironment(environment, water, sand, stone, grass, grassSide, sandSide, waterX, tree, player, trees, blocks, waterdraw, waterUpdateNeeded); 124 RedrawOverlay(overlay, clouds, playerSprite, player, cloud1x, cloud2x, maincurser); 125 126 //Draw Camera/HUD 127 DrawScreen(display, player, screen, environment, overlay); 128 129 //if(inventoryon){DrawInventory(readyBoxes, selficon, display, inventorybox);} 130 al_draw_bitmap(maincurser.graphic, maincurser.x - al_get_bitmap_width(maincurser.graphic)/2, 131 maincurser.y - al_get_bitmap_height(maincurser.graphic)/2, NULL); 132 133 al_flip_display(); 134 al_clear_to_color(al_map_rgb_f(0,0,0)); 135 } 136 }

When I call RedrayOverlay(), that is when the fps drops. RedrawOverlay() looks like this:

void RedrawOverlay(ALLEGRO_BITMAP *&overlay, ALLEGRO_BITMAP *&clouds,  ALLEGRO_BITMAP *&playerSprite, Player &player, int cloud1x, int cloud2x, Mouse maincurser)
{
  al_set_target_bitmap(overlay);  
  al_clear_to_color(al_map_rgba_f(0,0,0,0));
  al_draw_bitmap_region(playerSprite, 0, player.direction, 26, 26, player.x - 13, player.y - 13, NULL);
  //al_draw_filled_circle(player.x, player.y, 3, al_map_rgb_f(1,0,1));
  //al_draw_bitmap_region(clouds, , , WIDTH, HEIGHT, 0, 0, NULL);
  //al_draw_bitmap(clouds, cloud2x, 0, NULL);  
}

The al_draw_bitmap_region() is what makes the frame drop.

EDIT: After more testing, I found that most my drawing functions drop the frame rate significantly. However, drawing to the screen does not seem to affect it.

beoran
Member #12,636
March 2011

Let me guess, the overlay is a memory bitmap? Drawing to memory bitmaps is also relatively slow...

Edgar Reynaldo
Member #8,592
May 2007
avatar

There's got to be something more going on here. Drawing a single sprite should never drop your fps from 60 to 30 if it is hardware accelerated.

Are you sure all your bitmaps are loaded after the display is created? Your overlay could be a memory bitmap which would explain the slow drawing to it. There's got to be some other explanation.

I don't mind looking at the rest of your source code if you want to post it. Zip files are best.

sadelbrid
Member #15,200
June 2013

Okay here is my project folder.
EDIT: This is updated! Look at this one instead.

Edgar Reynaldo
Member #8,592
May 2007
avatar

Quote:

main.cpp#SelectExpand
57 ALLEGRO_BITMAP *tilemap = al_create_bitmap(125, 125); 58 ALLEGRO_BITMAP *environment = al_create_bitmap(al_get_bitmap_width(tilemap) * 32, al_get_bitmap_height(tilemap)*32); 59 ALLEGRO_BITMAP *overlay = al_create_bitmap(al_get_bitmap_width(tilemap) * 32, al_get_bitmap_height(tilemap)*32);

32X125 = 3750 + 250 = 4000

So your overlay texture is 4000 x 4000. That is likely too large of a texture for your graphics card to allocate. Most have a max size of 2048, 4096 if you're lucky. This means overlay is probably being created as a memory bitmap. Any reason you need a 4000x4000 overlay?

sadelbrid
Member #15,200
June 2013

Well I made an overlay for the hud, player, mobs, and other objects and use environment for things that would not change very often. I made it the same size as environment to avoid some math when drawing. I'll change it and let you know how it goes.

Edgar Reynaldo
Member #8,592
May 2007
avatar

The general paradigm nowadays is just to blast everything through the video card on every frame. And you can usually get away with it too. But I understand your desire to minimize excess drawing, it's only natural.

sadelbrid
Member #15,200
June 2013

I eliminated the giant 4000x4000 bitmaps and recoded the drawing functions to draw the tiles one at a time and now it's running at 60 fps! Thanks!

Chris Katko
Member #1,881
January 2002
avatar

So your overlay texture is 4000 x 4000. That is likely too large of a texture for your graphics card to allocate.

Though, for modern systems (*not crappy tablets), it shouldn't be unless perhaps you're trying to update the entire thing by drawing individual tiles to it (including wasting time drawing off the screen boundaries.)

That is, it's a throughput limit, not a hardware specification limitation.

Any card supporting OpenGL 4.1, for example, is required to support 16,384 x 16,384 as the lowest "maximum texture size" of a card. Which is 16384^2 * 32-bits / 1024 / 1024 / 1024 = 1 GB if uncompressed! :o There are some that list 2-D texture size at 64Kx64K! The future is amazing.

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs

Go to: