Hello folks.
So this problem is driving me crazy... I tried everything before coming here and bother you guys. But I really dont found whats up.
The explanation:
I'm programmin a game framework... for a long time, and I used to use allegro4 and sdl backends.. Now I'm programmin an allegro5 backend, because? Allegro5 Rules.
So, i "finished" my integration of the graphic module, but I'm finding some crazy problems in some situations..
For example this:Explanation after the code
I load a image and displays it in the screen... aplying some scale..
Note the line comented:
//images.push_back( Graphic::Image("hakumen_normal_map.pcx") ); Graphic::Image a("hakumen.pcx"); //images.push_back( Graphic::Image("hakumen_normal_map.pcx") );
If a uncoment the first line, all my program becomes soooo slow.
but if I uncomment the third line, it runs normally.
Is the same code! O.o
I know that its difficult to know whats happing wihout knowing the Image code and all. But all it does is load a allegro image and puts it inside.
I have used the Allegro Debug version and got the allegro.log, and surprise..
I dont know why, but when it becomes slow to hell I got lots of:
opengl D ogl_bitmap.c:649 ogl_lock_region [ 8,60037] Locking backbuffer opengl D ogl_bitmap.c:846 ogl_unlock_region [ 8,75334] Unlocking backbuffer
I think it calls this every step of the game.
And when it runs normal, i dont get this...
Here are the logs:
Please help, I'm getting crazy here, today I passed more than 3 hours running the debug mode, and finding nothing ...
If I understand the reason of the ogl_lock and ogl_unlock always,i can figure whats wrong..
You should post your Graphic::Image class constructor.
For my own curiosity and slightly unrelated to your question, could you talk briefly about your framework, what it aims to do and how it's generally constructed?
So.. I think I found whats causing this whole mess...
In the Image constructor, I load the image.. But I wanted that all my modules to be the most independent possible, so I have my own loading routines. in the allegro image routine i use something like this..
In this code, I'm forcing the load to paint each pixel of the image manually with green...
I set the image as target, after lock it, do putpixel operations...
unlock.
Now what I have discovered... If I create a image small, the program runs fine, if the image is big, than, welcome slowdown.
So what I think is: if there are many put pixel operations the program goes slow...
What do you think?
Now, Mark Oates:
This framework I started more than 4 years ago when I was in the university, the main goal was to build a game framework, easy of use, fast, and so on. What happened, I was without time, and I couldn't do all that I wanted. That Time,I was making it in C. Then time changed I started to make a new one in C++, much better for a game I was making called Rabbitz, I have posted about this game here a long time ago. And I have posted here about a megaman engine I was building, that engine uses the first version of my framework, in C.
So, after that I made my framework all in c++. The main goals: multiplataform, working in a system based in backends: You choose the lib that will render, like, allegro, sdl, allegro5. Why? I wanted to have the most plataforms possible.
The framework has some modules, like:
Audio
Core
Graphic
Input
Physics
Script
and some other modules that I will remove when I have ported them all.
This framework works with lua, as a script language, and chipmunk as a physics lib.
Graphic works with allegro4, allegro5(almost), SDL;
Audio audiere, and I'm porting a openAL backend because, audiere isn't compatible with MacOs.
Besides, I have a Editor, with sprites, animations and sound packages.
After the framework middle age, I started to program a game engine totally based in scripts. And this engine is almost done, you program all your game with lua, and use the framework files, for sprites, audio, animations in your game.
The goal is: you have your game as a lua script, and a executable file, with the engine, if you want to port your game you only have to compile the engine in the new plataform or download it if other one had done it before you for example.
Um.. I think thats it. XD
So what I think is: if there are many put pixel operations the program goes slow...
Yes, both al_draw_pixel and al_put_pixel are very slow. Avoid them unless in special cases, like maybe use al_draw_pixel for certain particle effects. al_put_pixel is used on locked surfaces - usually just locking in a known format like RGBA then directly modifying the buffer is faster. But al_put_pixel can be easier to understand if speed doesn't matter and in some special cases you might lock to an unknown format in which case you need al_put_pixel.
Elis thats no the case..
I just use al_draw_pixel, when I'm loading my images, and I lock the image first..
it seems that when I use a lot of al_put_pixel, later on, on my main loop, every think becomes slow...
Like I said, this kind of operations is occuring very much:
opengl D ogl_bitmap.c:649 ogl_lock_region [ 8,60037] Locking backbuffer opengl D ogl_bitmap.c:846 ogl_unlock_region [ 8,75334] Unlocking backbuffer
And I dont know why.
Well, al_draw_pixel() will take as long as al_draw_bitmap() - which is quite slow, considering it only draws a single pixel.
What for are you calling al_put_pixel? It doesn't really make sense except for directly modifying memory/locked bitmaps. If you want to draw a single pixel (e.g. for particle effects), use al_draw_pixel.
I just use al_put_pixel in my loading functions.
WHy² because I have a separated module for loading files, I dont know if this will keep this way, but this is not the problem.
The problem is the "slowdown".
It happens, in my main loop, after put pixels and all.
In my main loop I just clear the buff , draw a image, and then flip the buffer.
But in some cases this ogl_lock, unlock, is happening too much...
I think it is that is causing the slowdowns...
Take a look at the log... you will see it.
What is the code for the draw() and clear() functions?
You should never use locking during the game... it will kill performance. (There's exceptions, like if you stream a video to a texture and have no other way to transfer the data.)
Elias I'm not locking/unlocking during the game...
I said that in the log i saw that the allegro is locking/unlocking without my comand.. I dont know why it is locking and unlocking every frame.
About the draw and clear functions they are pretty basic, just a wrapper in this example:
I was that the problem just happens for drawing operations. If I clear the image instead, it runs normal, but when I draw(every kind of draw),it becomes crazy.
Why do you clear the bitmap you are drawing? I assume you draw everything to an intermediate buffer and then only draw that. Some (old) cards don't like that. I assume if you never change the target bitmap the slowdown disappears.
I don't clear the bitmap I'm drawing, I just clear the display.
display.clear(Graphic::Color(1.0f ,0.0f ,0.5f, 1.0 ) ); //limpa a tela a.draw(position, a.getWidth()*zoom, a.getHeight()*zoom, Graphic::Mirroring::Normal ); al_flip_display();
Btw, i made more test today, and I figure out, looking into the allegro locks that when the slowdown happens there is 2 locks into the bitmap, but only one unlock... But I explicity call lock, then unlock, one time each. And I putted a printf there, and i comproved that My calls are correct, one for each, but why the allegro are calling 2 locks? look at these lines in the log:
The Fast:
opengl D ogl_bitmap.c:1076 _al_ogl_create_bitmap [ 0,75770] Creating OpenGL bitmap opengl D ogl_bitmap.c:1098 _al_ogl_create_bitmap [ 0,75775] Using dimensions: 350 350 opengl D ogl_bitmap.c:1107 _al_ogl_create_bitmap [ 0,75779] Chose format ABGR_8888 for OpenGL bitmap dtor D dtor.c:184 _al_register_destructor [ 0,77158] added dtor for object 0x944cd18, func 0xedc0db opengl D ogl_display.c:194 setup_fbo [ 0,77169] Created FBO: 1 opengl D ogl_bitmap.c:679 ogl_lock_region [ 0,77181] Locking non-backbuffer READWRITE display D xfullscreen.c:974 _al_xglx_handle_mmon_event [ 0,82355] got event 28 opengl D ogl_bitmap.c:892 ogl_unlock_region [ 0,96023] Unlocking non-backbuffer READWRITE
The Slow:
opengl D ogl_bitmap.c:1076 _al_ogl_create_bitmap [ 0,79280] Creating OpenGL bitmap opengl D ogl_bitmap.c:1098 _al_ogl_create_bitmap [ 0,79287] Using dimensions: 350 350 opengl D ogl_bitmap.c:1107 _al_ogl_create_bitmap [ 0,79291] Chose format ABGR_8888 for OpenGL bitmap dtor D dtor.c:184 _al_register_destructor [ 0,80180] added dtor for object 0x95339e8, func 0x8790db opengl D ogl_bitmap.c:679 ogl_lock_region [ 0,80190] Locking non-backbuffer READWRITE opengl D ogl_bitmap.c:671 ogl_lock_region [ 0,84405] Locking non-backbuffer WRITEONLY opengl D ogl_bitmap.c:888 ogl_unlock_region [ 0,84568] Unlocking non-backbuffer WRITEONLY dtor D dtor.c:214 _al_unregister_destructor [ 0,85012] removed dtor for object 0x9546ca8
OOOO This is driving me crazy.:(
al_set_target_bitmap(mData);
al_clear_to_color( gorgonColort2AllegroColor(pColor) );//just normal conversion, not big
al_set_target_bitmap(aux);
So "aux" and "mData" are the same?
Btw, i made more test today, and I figure out, looking into the allegro locks that when the slowdown happens there is 2 locks into the bitmap, but only one unlock... But I explicity call lock, then unlock, one time each.
That would explain the slowness. What is the difference between your two logs? Or are you saying the same program, when you run it multiple times, will behave differently?
Are you calling any graphics functions other than al_put_pixel or al_draw_pixel while a bitmap is locked?
Aux is the previous target.
I save the previous target, set the new one(just for cleaning), clear, and set back the older.
To generate my logs, i have done this:
just one cicle of the main loop, and a return 0 after it.
So, The slow one, I simulate the situation describe in the first message, I uncommented the first images.push_back( Graphic::Image("hakumen_normal_map.pcx") );
to siulate the fast and normal behavior, I uncommented the second.
Thats all.
and after, vimdiff in both logs.
Edit:
The slowdown happens when I try to draw every image I create after the first...
Edit2:
I found the problem.
In the Image destructor I was doing this:
ImageBase::~ImageBase() { if(mData != NULL) { if( al_get_target_bitmap() == mData ) { al_set_target_bitmap(NULL); } al_destroy_bitmap(mData); } }
When I commented the al_set_target_bitmap()
Everything is back to normal...
WHY?????
What for is that if? Why would you ever destroy the current target bitmap?
Are you maybe trying to destroy a bitmap you don't own (like the backbuffer)?
I putted that in the destructor just to erase the target if i would destroy the image. Just ti erase the trash pointer. But the funny fact is that,
if a call al_set_target_bitmap(NULL) everywhere in my code, it will get this slow down. no matter where, if I put this, my program becomes slow...
Edit
It just becomes slow if I call al_set_target_bitmap(NULL)before creating my images, if I call after nothing happens. O.o
It just becomes slow if I call al_set_target_bitmap(NULL)before creating my images, if I call after nothing happens. O.o
Probably because at that point, allegro doesn't know what display to attach your bitmaps to, so it creates memory bitmaps. Which as you've noticed, is slow.
For my own curiosity and slightly unrelated to your question, could you talk briefly about your framework, what it aims to do and how it's generally constructed?
KGM v2.0
So to test this behavior, I have made a small program so simulate it..
And if I comment the "al_set_target_bitmap(NULL);" it all work normal, it it remains there, slowdown.
Now I see it, when I create some bitmap with no target_bitmap = memory bitmaps and slowww. Thanks to explain this to me Thomas.
btw KGM 2.0 O.o ? I dont get. kkk
Well, as Tomasu said, never call al_set_target_bitmap(NULL) or you get memory bitmaps.