Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Terrible Sprites Per Frame

This thread is locked; no one can reply to it. rss feed Print
Terrible Sprites Per Frame
Paragon
Member #15,335
October 2013

I must be doing something terribly wrong.
Similiar code in C# (using XNA) requires 40k-50k sprites drawn per frame to drop it to 60FPS,
but using ALLEGRO with Direct3D is only able to render 9000 sprites per frame before falling below 60FPS. Can someone please help me figure out what I am doing wrong?

Main.cs only calls RendererTest();
Even If I directly call the draws from RendererTest (The commented section)
i still get ~9000 draws per frame

I am fairly certain that I am using DirectX, When I run it using OpenGL the frames number of sprites I can draw per frame drop even further.

The profiler says that the majority of time is being spent in al_created_d3d_bitmap which, I can't figure out why that would be the case, b/c I initialize everything before the main loop, so by the time i start the profiler, It shouldn't even be called.

RendererTest.cs

#SelectExpand
1#pragma once 2#include <allegro5\allegro.h> 3#include <allegro5\allegro_image.h> 4#include <allegro5/allegro_font.h> 5#include <allegro5/allegro_ttf.h> 6//#include <allegro5\allegro_opengl.h> 7#include <allegro5\allegro_direct3d.h> 8#include "WorldState.h" 9#include "Renderer.h" 10#include <boost/lexical_cast.hpp> 11#include <string.h> 12 13void DirectDraw(int drawCount,ALLEGRO_BITMAP* ply, BOX spriteBox); 14void RendererDraw(Renderer* renderer,int drawCount, ALLEGRO_BITMAP* ply, BOX spriteBox); 15 16void RunRendererTest() 17{ 18 al_init(); 19 al_install_keyboard(); 20 al_init_image_addon(); 21 al_init_ttf_addon(); 22 23 al_set_new_display_option(ALLEGRO_RENDER_METHOD, 1, ALLEGRO_SUGGEST); 24 al_set_new_display_option(ALLEGRO_VSYNC, 2, ALLEGRO_SUGGEST); 25 al_set_new_display_option(ALLEGRO_CAN_DRAW_INTO_BITMAP, 1, ALLEGRO_SUGGEST); 26 27 //al_set_new_display_flags(ALLEGRO_OPENGL); 28 al_set_new_display_flags(ALLEGRO_DIRECT3D); 29 30 ALLEGRO_DISPLAY* display = al_create_display(800,600); 31 ALLEGRO_BITMAP* backBuffer = al_get_backbuffer(display); 32 ALLEGRO_FONT* font; 33 34 printf("RENDER METHOD: %i\n",al_get_display_option(display,ALLEGRO_RENDER_METHOD)); 35 printf("VSYNC: %i\n",al_get_display_option(display,ALLEGRO_VSYNC)); 36 printf("Can draw into bitmap: %i\n",al_get_display_option(display,ALLEGRO_CAN_DRAW_INTO_BITMAP)); 37 printf("Single Buffer: %i\n",al_get_display_option(display,ALLEGRO_SINGLE_BUFFER)); 38 printf("ALLEGRO_SWAP_METHOD: %i\n",al_get_display_option(display,ALLEGRO_SWAP_METHOD)); 39 printf("ALLEGRO_AUX_BUFFERS: %i\n", al_get_display_option(display,ALLEGRO_AUX_BUFFERS)); 40 41 int bitmapFlags = al_get_bitmap_flags(backBuffer); 42 if ((bitmapFlags&ALLEGRO_MEMORY_BITMAP)==ALLEGRO_MEMORY_BITMAP) printf("Memory Bitmap\n"); 43 if ((bitmapFlags&ALLEGRO_VIDEO_BITMAP)==ALLEGRO_VIDEO_BITMAP) printf("Video Bitmap\n"); 44 45 ALLEGRO_EVENT_QUEUE* systemQueue=al_create_event_queue(); 46 al_register_event_source(systemQueue,al_get_keyboard_event_source()); 47 48 WorldState ws; 49 50 ALLEGRO_PATH *path = al_get_standard_path(ALLEGRO_RESOURCES_PATH); 51 al_append_path_component(path, "Resources"); 52 al_append_path_component(path, "Sprites"); 53 al_set_path_filename(path, "blueShip.png"); 54 ALLEGRO_BITMAP* ply=al_load_bitmap(al_path_cstr(path, '\\')); 55 if (!ply) 56 { 57 printf("ERROR Loading sprite"); 58 ws.isDone=true; 59 } 60 61 al_set_path_filename(path,"spriteSheet.png"); 62 ALLEGRO_BITMAP* spriteSheet=al_load_bitmap(al_path_cstr(path,'\\')); 63 if (!spriteSheet) 64 { 65 printf("ERROR Loading sprite sheet"); 66 ws.isDone=true; 67 } 68 al_destroy_path(path); 69 70 71 path = al_get_standard_path(ALLEGRO_RESOURCES_PATH); 72 al_append_path_component(path, "Resources"); 73 al_append_path_component(path, "Fonts"); 74 al_set_path_filename(path, "pirulen.ttf"); 75 font = al_load_ttf_font(al_path_cstr(path, '\\'),12,0); 76 if (!font) 77 { 78 printf("ERROR loading font"); 79 ws.isDone = true; 80 } 81 82 ALLEGRO_EVENT evt; 83 evt.type=ALLEGRO_EVENT_KEY_UP; 84 while (evt.type!= ALLEGRO_EVENT_KEY_DOWN) 85 al_wait_for_event(systemQueue,&evt); 86 87 int drawCount=100; 88 int currCount=0; 89 Renderer r(display); 90 91 int w=al_get_bitmap_width(ply); 92 int h=al_get_bitmap_height(ply); 93 BOX spriteBox={0,0,w,h}; 94 BOX tileBox={1,1,32,32}; 95 96 while(!ws.isDone) 97 { 98 ws.Update(); 99 //COORD p={0,6}; 100 //SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),p); 101 ws.Draw(); 102 103 if (!al_event_queue_is_empty(systemQueue)) 104 { 105 ALLEGRO_EVENT ev; 106 al_wait_for_event(systemQueue,&ev); 107 if (ev.type==ALLEGRO_EVENT_KEY_DOWN) 108 { 109 if (ev.keyboard.keycode==ALLEGRO_KEY_ESCAPE) 110 ws.isDone=true; 111 if (ev.keyboard.keycode==ALLEGRO_KEY_A) 112 drawCount+=100; 113 if (ev.keyboard.keycode==ALLEGRO_KEY_Z) 114 drawCount-=100; 115 if (ev.keyboard.keycode==ALLEGRO_KEY_S) 116 drawCount+=10; 117 if (ev.keyboard.keycode==ALLEGRO_KEY_X) 118 drawCount-=10; 119 } 120 } 121 std::string o = "DrawCount:"; 122 o = o + boost::lexical_cast<std::string>(drawCount); 123 124 std::string oo = "FPS:"; 125 oo = oo + boost::lexical_cast<std::string>(ws.FPS); 126 al_clear_to_color(al_map_rgb(0, 0, 0)); 127 al_draw_text(font, al_map_rgb(255, 255, 255), 200, 200, ALLEGRO_ALIGN_LEFT, o.c_str()); 128 al_draw_text(font, al_map_rgb(255, 255, 255), 200, 300, ALLEGRO_ALIGN_LEFT, oo.c_str()); 129 RendererDraw(&r, drawCount, spriteSheet, tileBox); 130 //al_clear_to_color(al_map_rgb(0,0,0)); 131 //for(int i=0;i<drawCount;i++) 132 //{ 133 // al_draw_tinted_scaled_rotated_bitmap_region(spriteSheet, 134 // tileBox.X1,tileBox.Y1,tileBox.W,tileBox.H, 135 // al_map_rgb(255,255,255), 136 // tileBox.X1+tileBox.W/2.0,tileBox.Y1+tileBox.H/2.0, 137 // i%300+100,(i/300)+100, 138 // 1,1, 139 // 0,0); 140 //} 141 //al_flip_display(); 142 } 143 al_destroy_event_queue(systemQueue); 144} 145 146void RendererDraw(Renderer* renderer,int drawCount, ALLEGRO_BITMAP* ply, BOX spriteBox) 147{ 148 for(int i=0;i<drawCount;i++) 149 { 150 BOX drawBox={i%300,(i/300),spriteBox.W,spriteBox.H}; 151 renderer->Add(ply,spriteBox,drawBox,0,al_map_rgb(255,255,255),0); 152 } 153 renderer->Render(); 154}

Renderer.h

#SelectExpand
1#include <vector> 2#include <cstdlib> 3 4struct BOX 5{ 6 float X1; 7 float Y1; 8 float X2(){return X1+W;} 9 float Y2(){return Y1+H;} 10 float W; 11 float H; 12}; 13 14struct renderInfo 15{ 16 ALLEGRO_BITMAP* SpriteSheet; 17 BOX SpriteBox; 18 BOX DrawBox; 19 ALLEGRO_COLOR Tint; 20 float Rotation; 21 int Layer; 22 bool operator< (renderInfo &ri2) const 23 { 24 if (Layer!=ri2.Layer) return Layer<ri2.Layer; 25 if(DrawBox.Y1!=ri2.DrawBox.Y1) return DrawBox.Y1<ri2.DrawBox.Y1; 26 return false; 27 } 28}; 29 30class Renderer 31{ 32private: 33 std::vector<renderInfo> renderList; 34 renderInfo ri; 35 ALLEGRO_COLOR bgClearClr; 36public: 37 ALLEGRO_DISPLAY* display; 38 39 Renderer::Renderer(ALLEGRO_DISPLAY* d){ 40 display = d; 41 bgClearClr=al_map_rgb(0,0,0); 42 renderList.reserve(5000); 43 al_set_target_backbuffer(d); 44 } 45 46 Renderer::~Renderer(void){} 47 48 void Renderer::Add(ALLEGRO_BITMAP* spriteSheet, BOX spriteBox, BOX drawBox, float rot, ALLEGRO_COLOR tint, int Layer) 49 { 50 renderInfo r={spriteSheet,spriteBox,drawBox,tint,rot,Layer}; 51 renderList.push_back(r); 52 } 53 54 void Render() 55 { 56 std::sort(renderList.begin(),renderList.end()); 57 58 for(unsigned int i=0;i<renderList.size();i++) 59 { 60 al_draw_tinted_scaled_rotated_bitmap_region(renderList[i].SpriteSheet, 61 renderList[i].SpriteBox.X1,renderList[i].SpriteBox.Y1,renderList[i].SpriteBox.W,renderList[i].SpriteBox.H, 62 renderList[i].Tint, 63 renderList[i].SpriteBox.X1+renderList[i].SpriteBox.W/2.0,renderList[i].SpriteBox.Y1+renderList[i].SpriteBox.H/2.0, 64 renderList[i].DrawBox.X1,renderList[i].DrawBox.Y1, 65 renderList[i].DrawBox.W/renderList[i].SpriteBox.W, renderList[i].DrawBox.H/renderList[i].SpriteBox.H, 66 renderList[i].Rotation,0); 67 } 68 renderList.clear(); 69 al_flip_display(); 70 } 71};

taronĀ 
Member #10,584
January 2009
avatar

std::sort(renderList.begin(),renderList.end());

This might be part of your problem, sorting the renderList every frame, sorting is quite an expensive operation (Sort only on frames when something new was added?).
I believe XNA does not use the CPU to sort, but the GPU. (Depth-buffering)

Also you might want to use al_draw_textf for your formatting instead of creating and appending to strings every frame. I think it performs better, but I'm not sure.

Trent Gamblin
Member #261
April 2000
avatar

al_hold_bitmap_drawing and atlases, if you're not.

Aikei_c
Member #14,871
January 2013
avatar

That's actually the biggest problem with allegro for me, I have terrible fps too, even when just drawing the same image over and over in a simple test.
Concerning soring: no, sorting shouldn't be that slow. I also use isometric sorting in my game, and it hardly takes up 5% of my program's time, most time is actually taken by allegro draw functions.
However, your words about fps in XNA remainded me that I never compared allegro's fps on my PC to performance of anything else. I might try SDL and compare results in the future.

SiegeLord
Member #7,827
October 2006
avatar

It'd be very helpful if a self-contained example was posted. I certainly would like to know how al_created_d3d_bitmap shows up in a profiler (and what is the identity of that function, because no such function actually exists).

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

Kris Asick
Member #1,424
July 2001

Paragon said:

Similiar code in C# (using XNA) requires 40k-50k sprites drawn per frame to drop it to 60FPS,
but using ALLEGRO with Direct3D is only able to render 9000 sprites per frame before falling below 60FPS. Can someone please help me figure out what I am doing wrong?

Actually, that sounds about right if you're using mid-range hardware. :P

Allegro has a lot of overhead going on in the background when you perform rendering calls, which is handled by the CPU, so if you need to exceed Allegro's limitations you need to get a little more creative. For instance, prepping everything for render using a single large texture in an array of vertices and texture coordinates, then rendering that entire thing in a single call to al_draw_prim().

One other thing you could do is look into calling al_hold_bitmap_drawing() at the start and end of your rendering blocks and making sure that all sprites using the same source bitmap (not necessarily the same sub-bitmap) are grouped together in their drawing calls, as the less times you have to switch the active texture on the GPU, the better. ;)

But I have to wonder, what the heck you could possibly be doing that requires using over 9000 sprites per frame... :o

--- Kris Asick (Gemini)
--- http://www.pixelships.com

Paragon
Member #15,335
October 2013

@Kris Asick:
Do you have a link or can you elaborate on the part about using al_draw_prim()?
Also, I don't particularly require 9000 sprites and certainly not 50k per frame, but I wanted see what the max was without any game logic so I could bench mark how badly various bits of game logic are slowing the game down... I just figured that if i started with the ability to draw 50k, it would give me more wiggle room for AI, and path finding then if i started @9k... does that make sense or am I thinking about it wrong?

@Trent Gamblin:
The tile atlas doesn't apply in this case because it is a single sprite, but the al_hold_bitmap_drawing certainly did... 50k sprites per frame before hitting 60fps, so the atlases will certainly come in handy when handling actual sprites/rendering.

@SiegeLord:
Sorry, i think it was al_d3d_create_bitmap I don't think it is part of the public API, it must be part of allegro's internals... but I know that the profiler listed it as taking 50-80% of the time used by the RunRenderTest function (the main function in the code below).

Self contained source:
Requires rewriting LoadSprite to load a 32x32 png
Requires rewriting LoadFOnt to load a font

#SelectExpand
1#include <time.h> 2#include <stdio.h> 3#include <allegro5\allegro.h> 4#include <allegro5\allegro_image.h> 5#include <allegro5\allegro_font.h> 6#include <allegro5\allegro_ttf.h> 7//#include <allegro5\allegro_opengl.h> 8#include <allegro5\allegro_direct3d.h> 9 10ALLEGRO_BITMAP* LoadSprite() 11{ 12 ALLEGRO_PATH *path = al_get_standard_path(ALLEGRO_RESOURCES_PATH); 13 al_append_path_component(path, "Resources"); 14 al_append_path_component(path, "Sprites"); 15 al_set_path_filename(path, "blueShip.png"); 16 ALLEGRO_BITMAP* sprite = al_load_bitmap(al_path_cstr(path, '\\')); 17 if (!sprite) 18 printf("ERROR Loading sprite from %s", al_path_cstr(path,'\\')); 19 al_destroy_path(path); 20 return sprite; 21} 22 23ALLEGRO_FONT* LoadFont() 24{ 25 ALLEGRO_PATH* path = al_get_standard_path(ALLEGRO_RESOURCES_PATH); 26 al_append_path_component(path, "Resources"); 27 al_append_path_component(path, "Fonts"); 28 al_set_path_filename(path, "pirulen.ttf"); 29 ALLEGRO_FONT* font = al_load_ttf_font(al_path_cstr(path, '\\'), 12, 0); 30 if (!font) 31 printf("ERROR loading font from %s", al_path_cstr(path, '\\')); 32 al_destroy_path(path); 33 return font; 34} 35 36class WorldState 37{ 38private: 39 clock_t _startTime; 40 clock_t _frameTime; 41 clock_t _totalElapsedClocks; 42 clock_t _clocksSinceLastUpdate; 43 44 clock_t elapsed; 45 int updates; 46 int draws; 47public: 48 bool isDone; 49 int UPS; 50 int FPS; 51 float TimeSinceLastUpdate; 52 53 float TotalElapsedTime; 54 55 56 WorldState() 57 { 58 _startTime = clock(); 59 _frameTime = clock(); 60 _totalElapsedClocks = 0; 61 _clocksSinceLastUpdate = 0; 62 elapsed = 0; 63 updates = 0; 64 draws = 0; 65 FPS = 0; 66 UPS = 0; 67 isDone = false; 68 } 69 ~WorldState(void){} 70 boolean Update(void) 71 { 72 clock_t newFrameTime = clock(); 73 _clocksSinceLastUpdate = newFrameTime - _frameTime; 74 if (_clocksSinceLastUpdate <= 0) 75 return false; 76 updates++; 77 _totalElapsedClocks += _clocksSinceLastUpdate; 78 elapsed += _clocksSinceLastUpdate; 79 80 if (elapsed>CLOCKS_PER_SEC) 81 { 82 UPS = updates; 83 FPS = draws; 84 elapsed = 0; 85 updates = 0; 86 draws = 0; 87 } 88 _frameTime = newFrameTime; 89 return true; 90 } 91 92 void Draw(void) 93 { 94 draws++; 95 } 96}; 97struct BOX 98{ 99 float X1; 100 float Y1; 101 float X2(){ return X1 + W; } 102 float Y2(){ return Y1 + H; } 103 float W; 104 float H; 105}; 106 107void main() 108{ 109 al_init(); 110 al_install_keyboard(); 111 al_init_image_addon(); 112 al_init_ttf_addon(); 113 114 al_set_new_display_option(ALLEGRO_RENDER_METHOD, 1, ALLEGRO_REQUIRE); 115 al_set_new_display_option(ALLEGRO_VSYNC, 2, ALLEGRO_REQUIRE); 116 al_set_new_display_option(ALLEGRO_CAN_DRAW_INTO_BITMAP, 1, ALLEGRO_REQUIRE); 117 118 //al_set_new_display_flags(ALLEGRO_OPENGL); 119 al_set_new_display_flags(ALLEGRO_DIRECT3D); 120 121 ALLEGRO_DISPLAY* display = al_create_display(800, 600); 122 ALLEGRO_BITMAP* backBuffer = al_get_backbuffer(display); 123 124 125 printf("RENDER METHOD: %i\n", al_get_display_option(display, ALLEGRO_RENDER_METHOD)); 126 printf("VSYNC: %i\n", al_get_display_option(display, ALLEGRO_VSYNC)); 127 printf("Can draw into bitmap: %i\n", al_get_display_option(display, ALLEGRO_CAN_DRAW_INTO_BITMAP)); 128 printf("Single Buffer: %i\n", al_get_display_option(display, ALLEGRO_SINGLE_BUFFER)); 129 printf("ALLEGRO_SWAP_METHOD: %i\n", al_get_display_option(display, ALLEGRO_SWAP_METHOD)); 130 printf("ALLEGRO_AUX_BUFFERS: %i\n", al_get_display_option(display, ALLEGRO_AUX_BUFFERS)); 131 132 int bitmapFlags = al_get_bitmap_flags(backBuffer); 133 if ((bitmapFlags&ALLEGRO_MEMORY_BITMAP) == ALLEGRO_MEMORY_BITMAP) printf("Memory Bitmap\n"); 134 if ((bitmapFlags&ALLEGRO_VIDEO_BITMAP) == ALLEGRO_VIDEO_BITMAP) printf("Video Bitmap\n"); 135 136 ALLEGRO_EVENT_QUEUE* systemQueue = al_create_event_queue(); 137 al_register_event_source(systemQueue, al_get_keyboard_event_source()); 138 139 WorldState ws; 140 141 ALLEGRO_BITMAP* ply = LoadSprite(); 142 ALLEGRO_FONT* font = LoadFont(); 143 144 if (!font) 145 ws.isDone = true; 146 BOX spriteBox; 147 BOX tileBox; 148 149 if (ply){ 150 if (al_is_compatible_bitmap(ply)) 151 printf("Compatible"); 152 else 153 printf("Incompatible"); 154 int w = al_get_bitmap_width(ply); 155 int h = al_get_bitmap_height(ply); 156 spriteBox = { 0, 0, w, h }; 157 tileBox = { 1, 1, w, h }; 158 } 159 else 160 { 161 ws.isDone = true; 162 } 163 164 165 ALLEGRO_EVENT evt; 166 evt.type = ALLEGRO_EVENT_KEY_UP; 167 while (evt.type != ALLEGRO_EVENT_KEY_DOWN) 168 al_wait_for_event(systemQueue, &evt); 169 170 int drawCount = 100; 171 int currCount = 0; 172 while (!ws.isDone) 173 { 174 ws.Update(); 175 ws.Draw(); 176 if (!al_event_queue_is_empty(systemQueue)) 177 { 178 ALLEGRO_EVENT ev; 179 al_wait_for_event(systemQueue, &ev); 180 if (ev.type == ALLEGRO_EVENT_KEY_DOWN) 181 { 182 if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) 183 ws.isDone = true; 184 if (ev.keyboard.keycode == ALLEGRO_KEY_A) 185 drawCount += 1000; 186 if (ev.keyboard.keycode == ALLEGRO_KEY_Z) 187 drawCount -= 1000; 188 if (ev.keyboard.keycode == ALLEGRO_KEY_S) 189 drawCount += 100; 190 if (ev.keyboard.keycode == ALLEGRO_KEY_X) 191 drawCount -= 100; 192 } 193 } 194 al_clear_to_color(al_map_rgb(0, 0, 0)); 195 /*DRAWING WITH LEAST AMOUNT OF OVERHEAD START*/ 196 for (int i = 0; i<drawCount; i++) 197 { 198 al_draw_tinted_scaled_rotated_bitmap_region(ply, 199 0, 0, 32, 32, 200 al_map_rgb(255, 255, 255), 201 16, 16, 202 (i % 100)*5, (i / 100)*5, 203 1, 1, 204 0, 0); 205 } 206 al_draw_textf(font, al_map_rgb(255, 255, 255), 550, 10, ALLEGRO_ALIGN_LEFT, "Draw Count: %i", drawCount); 207 al_draw_textf(font, al_map_rgb(255, 255, 255), 550, 30, ALLEGRO_ALIGN_LEFT, "FPS: %i", ws.FPS); 208 al_flip_display(); 209 /*DRAWING WITH LEAST AMOUNT OF OVERHEAD END*/ 210 } 211 al_destroy_event_queue(systemQueue); 212}

Edgar Reynaldo
Member #8,592
May 2007
avatar

There are a few things to mention.

1. You forgot al_hold_bitmap_drawing in your code. Even if you're only drawing one sprite it helps if you're drawing it many times at once. Wrap the loop with a pair of hold drawing calls the first true and the second false, and your drawing times should decrease substantially.

2. clock() returns total processor time on Linux/Unix, and total time past on Windows. It's not a good way to measure time. Use an ALLEGRO_TIMER to tick once a second if you want to count fps and ups.
See https://www.allegro.cc/forums/thread/599033/791757#target for details.
And this old thread by GullRaDriel is gold if you're really interested in timing :
https://www.allegro.cc/forums/thread/585140

3. You forgot al_init_font_addon.

taronĀ 
Member #10,584
January 2009
avatar

void main()

Only int main() or int main(int argc, char *argv[]) is legal C/C++.

Kris Asick
Member #1,424
July 2001

Paragon said:

Do you have a link or can you elaborate on the part about using al_draw_prim()?

Unfortunately, no. I'm speaking from experience in that, al_draw_prim() has a huge overhead cost to call, but can send massive amounts of data to the video card in that single call, so if you use it correctly it can be very powerful and can perform better than multiple al_draw_bitmap() calls, but to use it, you need to manually assign all of your texture coordinates, triangle coordinates, vertex colours, etc., and put them all into a massive array you can send to the function.

Beyond that, just read the manual. :P

Quote:

Also, I don't particularly require 9000 sprites and certainly not 50k per frame, but I wanted see what the max was without any game logic so I could bench mark how badly various bits of game logic are slowing the game down... I just figured that if i started with the ability to draw 50k, it would give me more wiggle room for AI, and path finding then if i started @9k... does that make sense or am I thinking about it wrong?

You're thinking about it wrong. You'd be surprised how much game logic you can process without affecting the framerate on today's computers. Heck, I was running particle engines at 70 FPS using Allegro 4 back in 2000 on original Pentium CPUs. ;)

Plus, if your game logic DOES slow the game down, there's almost certainly going to be alternative approaches. For instance, if you have a massive tile-based world and various objects in that world can update themselves at random, instead of scanning every single tile every game tick and performing those random calculations, you could just scan a handful of random tiles and make it more likely the random tile event will happen when it gets scanned. Or, if you have tile entities that need to constantly be updated, instead of scanning the entire map for changes, you make a list of each tile that needs to be updated every game tick and update that list as more such tiles are placed or removed.

--- Kris Asick (Gemini)
--- http://www.pixelships.com

SiegeLord
Member #7,827
October 2006
avatar

So I profiled this on Windows, and didn't get anything sensible (I used the VerySleepy profiler). I checked, and there are no calls to _al_create_d3d_bitmap inside the draw loop, so if your profiler shows that as the main function, your profiler is broken.

Anyway, I tested a few other things: I tried al_hold_bitmap_drawing as others have already suggested, and that made things 5x faster. Then I tried a light-weight replacement based on al_draw_prim in my FastDraw library and got it nearly 2x faster still (nearly 10x faster relative to the original). I am not aware of other techniques that will support faster drawing that the approach taken in that library given changing sprites every frame. If you can guarantee that you won't change your sprites often (e.g. it's a level tilemap) then Allegro 5.1 provides a feature to take it even further beyond, potentially adding 4x to 5x speed improvement on top of FastDraw's performance (i.e. perhaps as much as 50x faster than you current code).

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

Trent Gamblin
Member #261
April 2000
avatar

SiegeLord, I quickly looked at fast_draw.c, is it essentially the same thing as using al_draw_prim manually? I often do batch sprites up and draw them with al_draw_prim, would there be any difference besides ease of use?

SiegeLord
Member #7,827
October 2006
avatar

It's just for ease of use.

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

Trent Gamblin
Member #261
April 2000
avatar

Ok. I can see that being useful. I'm used to doing it manually. I'll try to remember it exists.

Go to: