PDA

View Full Version : TBitmap vs. CreateDIBsection



FusionWolf
22-09-2009, 12:10 PM
Hello fellow coders! ;)

At couple weeks a go I desided to create quickly a little Asteroids clone by using only Window GDI functions just for own fun.

But after a couple try I did not achieve as good framerates I liked to so, I begun to study why's that.

I stripped all extra away and start examining basic things of a game. My Window class was all good, my GameTimer class was also good, so it have to be the backbuffer blitting which slows down.

First I created a compatible DC and selected compatible bitmap to that. Performance was fairly good on my laptop, BUT my four year old AMD showed me the real situation. Framerate sucked. But not only the rate (which was something near 60fps) also the movement of the Shuttle (polygon) was jerky which it wasn't on laptop (which achieved 400fps).

I chanced my Backbuffer to TBitmap and voil?. Almost 4000 fps on laptop and 1000 on my gran-ol'-amd machine.

I tried to study what makes TBitmap so fast to blit (with bitblt). I noticed that it uses device indepented bitmap, so I decided to create one my own with GDI function.

After a while I learned the use of CreateDIBSection. Performance was littlebit better than with CreateCompatibleBitmap, but when compared to TBitmap it still sucked (something like 300fps). And still the graphics with that own DIB was jerky on my gran-ol'-amd machine. :o

And since then I have been studying-trying-testing-creating-implementing-and-you-name-whatever the creation and blitting of DIB but I still can't get more than 300fps no matter how I create DIB or blit it (StrechDIBits, BitBlt and etc.)

I have even found articles and examples how to tune performance of DIBS (here's the Microsofts own article http://support.microsoft.com/kb/230492) but there's still no go.

Ofcourse I could use TBitmap on my backbuffer that's no problem at all, but I'm pondering why I can't achieve same speed with my own created backbuffers.

Does anyone have an clue or idea because I'm out?!? ::)

I still liked to do my little game by just using Windows GDI functions for drawing. :P

ps. sorry my bad, bad, bad and poor english.


edit: this 'project' continues on here:
http://www.pascalgamedevelopment.com/forum/index.php?topic=5967.0

User137
22-09-2009, 08:44 PM
I have even found articles and examples how to tune performance of DIBS (here's the Microsofts own article http://support.microsoft.com/kb/230492) but there's still no go.
Were you able to correctly translate the C++ source?

FusionWolf
22-09-2009, 09:11 PM
Yes, I am cabable to convert C(++), Object Pascal, Turbo Pascal, Visual Basic and VBA between each to another.

I can also 'convert' finnish, english, swedish and germany among to each another. Not so good though than programming languages, but somehow anyway. :-[

I'm currently (right now actually :)) building a test application which has a timer that calculates framerate and shows it up on a window among other values like uptime. There will also be an option which kind of back buffer to use or no back buffer at all (direct textout to window canvas). Backbuffer is cleared and displayed on window at each loop.

No back buffer and TBitmap options are already handled and ready to go. Now I implement DIB backbuffering and after that I will share the application here, so everyone can test it out. I also share the source code so, if someone could point out what's wrong with it. :o

I tested those two options already with my laptop and got near 40k (Yup, 40 000 :)) frames per second without back buffer at all. And with TBitmap I got nearly 3500 frames per second.

Back to code and brb!! :)

edit: ouh, and I just remembered that I could use CreateCompatibleBitmap() as a one of the options, so there will be three different kind of back buffer and one option for no back buffer at all.

paul_nicholls
22-09-2009, 10:31 PM
good luck with that :)

cheers,
Paul

FusionWolf
22-09-2009, 11:05 PM
I have now implemented no back buffer, TBitmap and compatible bitmap options of application. I also imported my shuttle object (drawn as polygon) which is controlled with a arrow keys (GetAsyncKeyState).

I also have two different kind of timer in there now. First one uses QueryPerformanceCounter and second one TimeGetTime from MMSystem unit.

When TimeGetTime timer is used frame rate locks to 1000fps because the resolution of timer (ResultTime := (TimerStartTime - FrameEndTime) / 1000). And because minimum resolution of timer is 1ms, it's only possible to get 1000 time differences (cap between the frames) per second. Am I right?? ::)

But with that TimeGetTime -timer I achieve very, very, very smooth 'game play' (shuttles velocity) on my laptop, but when I copy executable to a computer wich has a one cpu core at use, game play gets really choppy. Even if there were enough frames per second!?! :o

So, at this point, after many emprical test of different computers (I have tested my exe's on couple other computers also, which are not mentioned earlier) I'm not sure what causes that jerky graphics.

It's obvious that different back buffers gives different framerates, but even in worst case (CompatibleBitmap) frames are so high on my desktop computer that game play should be nice and smooth, but no. :( Shuttle jumps some pixels ahead from time to time like some frames would be missing between the update of the loop, but that's not the issue. I have to sit down for a while and rethink where problem lies.

I'm going to continue my test application tomorrow so until then.... ???


edit: I desided to share the executable of an application. It uses that TimeGetTime timer and has No backbuffer, TBitmap (Blue canvas) and CompatibleBitmap (Green canvas) implemented. On my laptop everything works fine and goes smoothly but in my gran-ol'-amd desktop machine frames drops near to 60 (except with TBitmap) and graphics jitters big time (even with TBitmap).

Application is very, very, very unfinished and DIB mode is not implemented yet, but one can try if want to. :) There's also no error checking at all, so if something goes wrong it will propably leak memory and crash things. :o But, if all is initialized properly then cleanup is done also properly. ;)

Here it is -> http://www.saunalahti.fi/hag/share/GDIBlitting.exe

Source coming later when done!


Edit2: Ouh, and I liked to mentiot that, if I use DirectX to draw things. Even with same game engine as this example uses. Everything goes smooth and fine even with my Gran-ol'-amd machine. It's only the GDI which causes the headache, but that's the joy part of programming. Isn't it? ;)

FusionWolf
22-09-2009, 11:52 PM
Hmmm... this is going very weird. :o

Now, I noticed that if I had Delphi up and running and I start that my application. I get 1000 fps and everything goes smoothly. But if I close Delphi and try that .exe then I get same results as I get at my desktop computer. :'(

Graphics jitters and frames are drop near to 100. :o Even with TBitmap. Why's that? How come it acts like this? very odd! :o

FusionWolf
23-09-2009, 09:21 AM
This is going even more weird now!! :o

If I start that application which I shared here and choose a Delphis TBitmap as an back buffer for example. I get littlebit over 100 frames and graphics goes jerky if I don't have any other application running at the moment.

BUT if I open a Firefox and go to the webpage which has a flash animation on it and miminize it to the taskbar and start the application I get 1000fps and things goes smoothly!! :o

WTF!?! I'm so confused right now... And anyhow, if I use DirectX all goes well with decent 4000fps on windowed mode and nearly 8000fps on alt-tabbed to fullscreen mode.

Can someone else do the same test?? Or can someone raport something at all about how the application works on his/her computer??

Here's the link again: http://www.saunalahti.fi/hag/share/GDIBlitting.exe


edit: Ouh, if one ponders if there's something bad things hidden into the executable I can promise that won't be the case!! Go ahead, test and report!! :)
javascript:void(0);

edit2: Here's also very unfinished DirectX version of the engine. It uses bitmap to render the shuttle. Arrws move, LETF-CTRL fires missiles, F enabled/disables rendering statics and ALT-TAB goes between window and fullscreen. DirectX 9 libraries has been used when executable has been build.

Here you go: http://www.saunalahti.fi/hag/share/Meteors.zip


edit3: odd, odd, odd, odd and weird!! I tried that flash trick with a IE7, but there's no go. So, only when Firefox is opened application works great (or Delphi of course). This really is mysterious. ???

de_jean_7777
23-09-2009, 11:17 AM
I tried your application. I get pretty much consistent framerates for all cases which is from 90 ~ 150 FPS. With no backbuffer it sometimes jumps up to 900 ~ 1000 FPS but only for a brief moment. The only problem I've encountered(other than the low framerates) is that the DIB backbuffer does not display anything at all.

As for the game I get around consistent 1000 ~ 1100 FPS in windowed mode, for fullscreen I get 1800 ~ 2100 FPS though it sometimes jumps briefly to less (like 1400 FPS).

I am not sure why this is happening. It's quite bizzare. I think I've heard of something similar before but cannot remember. If I do remember I will post it. As for your timer, it seems kinda irratic. I'd suggest that you get the framerate once per second, instead of lower times you might be using.

As for my hardware, I have an AMD Athlon64 3000+ and an ATI Radeon X600 Pro (Catalyst 9.3) with 512 MiB RAM.

FusionWolf
23-09-2009, 11:34 AM
I tried your application. I get pretty much consistent framerates for all cases which is from 90 ~ 150 FPS...<clip>

Yeah, but does the shuttle move smoothly? In my computers when I get those framerates shuttle jumps ahed from time to time and moves jerky!!

And as I said at my earlier posts that DIB back buffer is not implemented yet! And if you read my later posts you notice that the problem is not backbuffer related at all because framerate goes very high when delphi is up and runing (go and try you self. Open delphi and run my GDI test application).

But very weird indeed.. :o



As for the game I get around consistent 1000 ~ 1100 FPS in windowed mode, for fullscreen I get 1800 ~ 2100 FPS though it sometimes jumps briefly to less (like 1400 FPS).

I am not sure why this is happening. It's quite bizzare. I think I've heard of something similar before but cannot remember. If I do remember I will post it. As for your timer, it seems kinda irratic. I'd suggest that you get the framerate once per second, instead of lower times you might be using.

As for my hardware, I have an AMD Athlon64 3000+ and an ATI Radeon X600 Pro (Catalyst 9.3) with 512 MiB RAM.


believe me, I have been testing all kind of the timers I ever have found from internet, but I will do more research for them.

I assume that the game (Meteors) moved smoothly on your PC? But I ponder you have so good omputer and still get only those framerates.. ???

User137
23-09-2009, 01:06 PM
I'm using TTimer myself most of the times :) Stable 60 fps without consuming cpu and gpu power for pointless frames. It actually keeps the cpu fans quiet too... but i was once experimenting with sleep() to achieve the same kind of cpu save but it didn't quite work that well.

Edit: Actually for current game i limited it to 30 fps.

de_jean_7777
23-09-2009, 04:04 PM
Yeah, but does the shuttle move smoothly?

The application moved relatively smoothly. However, the shuttle had a twitching movement(you could say it made small jumps). You can notice this when running without the backbuffer, as the shuttle leaves a inconsistent trail when it is supposed to run with consistent speed.



Open delphi and run my GDI test application
Don't have Delphi, but I don't think this is only related to Delphi.



I assume that the game (Meteors) moved smoothly on your PC?

The game ran very smoothly and the ship had a fluid motion. There were no signs of twitching movement.

FusionWolf
23-09-2009, 05:09 PM
YES!! Finally I got it right. ;D And thanks goes to de_jean_7777 for doubting my timing functions.

I made some test and noticed that my timer leaps forward on time to time for some sort of bug from Microsoft side (thats why my shuttle 'jumps' ahead between the frames). :o there's even knowledge artice on MSDN about that bug.

Now I'm using both timers (TimeGetTime and QueryPerformanceCounter) together and when other leaps ahead another, then time difference is fixed with some calculation of about what the time should be. (This I realized when I found an article telling about physics simulation on computer).

I also found that GetDevicaps() can retrieve minimum and maximum timer resolutions which I took to use with TimeBeginPeriod and TimeEndPeriod routines. ;D

Now everything goes smoothly with decent ~2000 frames per second at my laptop (Core 2 Duo T9500 @ 2,4GHz with nVidia Quadro FX 1600M 512MB)

Tomorrow I will put up a new application which can be downloaded from here with a source code. ;) No need for DIBs anymore. CompatibleBitmap does it what's expected. ;)

Thanks again de_jean_7777 to point me to the right tracks. :yes:


edit: And what comes to that Meteors 'game' it uses excactly the same timing functions than that GDI blit example, but DirectX handles the bad behavior somehow 'silent' at background. ???

Here's the executable with the new timer. It's still very, very unfinished (no error handling, no DIB back buffer, no optimization and etc.), but one can try and see the difference. :P

Here you go: http://www.saunalahti.fi/hag/share/GDIBlitting2.exe

de_jean_7777
23-09-2009, 05:57 PM
I am glad I was able to help and I am glad you got your application working. Microsoft is full of strange bugs.

I also tested the new application on my PII 400 with a nVidia TNT2 M64. Funnily, the framerate is similar to the one on my AMD computer, 120 ~ 150 FPS.

FusionWolf
24-09-2009, 01:02 PM
I have to resume on this timing issue problem. I already thought that all is fine and working, but no... :no:

I still noticed some glitches and jumps here and there with that second GDIBlitting example and begun wondering what the heck. ::)

After a while I realized that the loop goes so fast that there is no time difference between the call of TimeGetTime on each loop. :o

So, I made an array and begun to collect elapsed times between the updates into it. Array is size of 10 cells. Then I set a break point at the code after a tenth loop. I looked the values in the array on noticed that only 2 cells had a value other than zero!! :o (my GetTime() -method gives result in seconds how much time has passed since initiazation of timer class).

Then I made lot's and lot's of more similar tests and noticed same thing again and again. So the conclusion is that the loop goes so fast that timer has no resolution to measure the difference between calls. ;D

Now I implemented new timer. :) It collects elapsed times to array as I mentioned and calculates average of those time which isn't zeros. So, if array has 10 values and three of them is another than zero then the sum of those values is divided by three and that's the result of elapsed time since previous call. :)

I'm currently putting up a new test application (again) with this 'MyGameTimer' and share it here (with sources) later on today / night.

It uses compatible bitmap as an back buffer, which is actually all ok. ;) (the issue of a thread is not about a back buffer anymore as it was at the very begining :-[).

FusionWolf
24-09-2009, 09:07 PM
Okey, here it comes the final test application for this thread (finally) :-[

An executable with the sources as promised. The sources are not commented (except the timer part), but they are very self explanatory. ;D

I appreciate if people who try this would report how it works on their computer. :) Maybe the major specs. of the used computer would be also nice to know among the achieved FPS.

Ouh, and if there's something to point out at the source code, feel free to give a comment. Anykind of feedback is welcome. ;)

I continue to develop the 'real thing' (GDI version of Asteroids) and put up a link at here somewhere, where people can download it among with the source codes of course. ;)

But, here you go:

http://www.saunalahti.fi/hag/share/MyGame.zip


Use arrow keys to float around. :)

paul_nicholls
24-09-2009, 10:30 PM
I'm getting around 54-55 FPS on my work computer:

Win XP SP3
Intel(R) Core(TM)2 Quad CPU
2.83 GHz
3.35 GB RAM

cheers,
Paul

User137
25-09-2009, 04:31 AM
1000 fps exactly, didn't change anywhere during the whole runtime.

Intel Core 2 Duo E8400, 3 Ghz
2 GB RAM
Geforce 8600 GT

FusionWolf
25-09-2009, 05:27 AM
I'm getting around 54-55 FPS on my work computer:

Win XP SP3
Intel(R) Core(TM)2 Quad CPU
2.83 GHz
3.35 GB RAM

cheers,
Paul


That's very strange. ??? Which display adapter you may have on that computer? I'm also getting 1000fps as User137 (that's maximum) with 3 different computers.

- Intel Core2Duo T9500 @ 2,4GHz 2GB RAM and nVidia Quadro FX 1600M 512MB

- Intel Pentium 4 2,8Ghz 1GB RAM and ATI Radeon X300 128MB

- AMD Duron 1,6GHz 2GB RAM and ATI Radeon 9600XT 256MB


Can you tell me (approximately) what the rendering time is showing to you?

paul_nicholls
25-09-2009, 06:01 AM
I'm getting around 54-55 FPS on my work computer:

Win XP SP3
Intel(R) Core(TM)2 Quad CPU
2.83 GHz
3.35 GB RAM

cheers,
Paul


That's very strange. ??? Which display adapter you may have on that computer? I'm also getting 1000fps as User137 (that's maximum) with 3 different computers.

- Intel Core2Duo T9500 @ 2,4GHz 2GB RAM and nVidia Quadro FX 1600M 512MB

- Intel Pentium 4 2,8Ghz 1GB RAM and ATI Radeon X300 128MB

- AMD Duron 1,6GHz 2GB RAM and ATI Radeon 9600XT 256MB


Can you tell me (approximately) what the rendering time is showing to you?


The 54-55 FPS was with this file you gave us:

http://www.saunalahti.fi/hag/share/MyGame.zip

I have two graphics cards (as I have 3 monitors at work):
NVidia GeForce 8400 GS
NVidia GeForce FX 5200

The rendering time seems to be between 0.0184 - 0.0186
I hope this helps?

cheers,
Paul

FusionWolf
25-09-2009, 06:08 AM
The 54-55 FPS was with this file you gave us:

http://www.saunalahti.fi/hag/share/MyGame.zip

I have two graphics cards (as I have 3 monitors at work):
NVidia GeForce 8400 GS
NVidia GeForce FX 5200

The rendering time seems to be between 0.0184 - 0.0186
I hope this helps?

cheers,
Paul


Yes, that's the lates file I shared.

Maybe there's something to do with those multiple screens, I don't know... Perhaps. I have to do some test with multiple monitors on my working place.

Can you give me your averge rendering time which you see at the top of the game window?

Thank's for your very valuable reply. ;)

paul_nicholls
25-09-2009, 06:32 AM
The 54-55 FPS was with this file you gave us:

http://www.saunalahti.fi/hag/share/MyGame.zip

I have two graphics cards (as I have 3 monitors at work):
NVidia GeForce 8400 GS
NVidia GeForce FX 5200

The rendering time seems to be between 0.0184 - 0.0186
I hope this helps?

cheers,
Paul


Yes, that's the lates file I shared.

Maybe there's something to do with those multiple screens, I don't know... Perhaps. I have to do some test with multiple monitors on my working place.

Can you give me your averge rendering time which you see at the top of the game window?

Thank's for your very valuable reply. ;)


The rendering time seems to be between 0.0184 - 0.0186

so I suppose the average rendering time would be 0.0185 :D

cheers,
Paul

FusionWolf
25-09-2009, 06:55 AM
Paul, is the game play smooth (fluid motion) or is there somesort it twitching?

edit: Hmmm... maybe the TimeGetDevCaps() returns so 'big' time resolution for some reason that no faster timing isn't possible. :o

My second doubt is that compatible bitmap is not so comptible because of those two display adapters. So, GDI converts it's format on every blit and that's why the framerate drops.... perhaps. ???

Very strange indeed...

paul_nicholls
25-09-2009, 10:04 AM
Paul, is the game play smooth (fluid motion) or is there somesort it twitching?

edit: Hmmm... maybe the TimeGetDevCaps() returns so 'big' time resolution for some reason that no faster timing isn't possible. :o

My second doubt is that compatible bitmap is not so comptible because of those two display adapters. So, GDI converts it's format on every blit and that's why the framerate drops.... perhaps. ???

Very strange indeed...


The ship moves nice and smoothly so there is no problem with that part...

Don't know why I'm getting only 54-55 FPS on my work machine.

I just tried it on my home machine (single monitor setup):

WinXP SP2
AMD Athlon(tm) 64 Processor 3000+
1.81 GHz
1.00 GB RAM

NVidia GeForce 6600 (256MB RAM)

It runs around 1000FPS!
it was a bit jerky though with regards to the updating of the ship...but I suspect that is because other programs have been running slower/jerkily on my home machine lately.

I think I need to reboot, or even clean up windows with a re-install :(

cheers,
Paul

User137
25-09-2009, 03:59 PM
To add; the game was very smooth to play but it use 50% cpu power that is like full capacity of other core... well it divided like 15% and 85%, don't know why.

Edit: Also Delphi 7 compiled and run the game from source without any issues :)

FusionWolf
26-09-2009, 08:24 PM
To add; the game was very smooth to play but it use 50% cpu power that is like full capacity of other core... well it divided like 15% and 85%, don't know why.

Edit: Also Delphi 7 compiled and run the game from source without any issues :)


Correct. The game uses all cpu time what it gets because there's is no anykind of idling at the game loop. If you look the sources there's a Sleep(1) routine defined at the very begining of the timer update method, but it's commented out. It can be uncommented and re-compiled when game will use much less cpu cycles.

Also there's a SetThreadAffinityMask() routine at the begining of the application (in MyGame.dpr) which is commented out. It sets thread to use one cpu-core only. I used it earlier when game used QueryPerformanceCounter() for timing. But now, when only multimediatimer is used there's no worry about that timer will get incorrect values from cpu (if cores are not in sync). The system handles that how processor load is shared between the cores.

Nice to hear that it compiled fine. ;)

Paul, I find out also a one computer where was a 1000fps, but the movement of the shuttle was littlebit jerky. It stopped animation for a blink of an eye and then catched up the time by speeding up the animation to way too fast and stopped again and speeded up again and so on and so on....

I have no idea what causes that kind of behavior because most of the computers which I have been tested 'game' works all right.

I still keep studying about the timers if I could make it even better. For the game loop itself I have couple ideas. It could be optimized by measuring the speed of the computer, core count and etc. and setting some variables based on that so, they can be used for setting the idling times and etc. Make some estimations if I would say. :)

FusionWolf
30-09-2009, 08:00 AM
I have been noticed lately while testing my timer object with lates 'test game application' that, if Windows performance monitor is open it may put the 'test application' to twitch and makes movement of objects look jerky. >:(

Especially on computers with a single cpu core. So, I recommend not to view Windows Performance monitor while playing. :D

Here's the latest executable of "My Game". Sources are not available at the moment, but will be when it's done (soon I hope ;)).

I would still appreciate any feedback how "game" works on which kind of computer - thanks! ;)

Here you Go -> http://www.saunalahti.fi/~hag/share/MyGame2.exe

edit: Arrows moves and CTRL shoots.

paul_nicholls
30-09-2009, 08:14 AM
I have been noticed lately while testing my timer object with lates 'test game application' that, if Windows performance monitor is open it may put the 'test application' to twitch and makes movement of objects look jerky. >:(

Especially on computers with a single cpu core. So, I recommend not to view Windows Performance monitor while playing. :D

Here's the latest executable of "My Game". Sources are not available at the moment, but will be when it's done (soon I hope ;)).

I would still appreciate any weedback how "game" work on which kind of computer - thanks! ;)

Here you Go -> http://www.saunalahti.fi/~hag/share/MyGame2.exe


Same stats as before on my work machine - 54-55 FPS, and rock solid :)

cheers,
Paul

User137
30-09-2009, 03:11 PM
I would still appreciate any feedback how "game" works on which kind of computer - thanks! ;)

Here you Go -> http://www.saunalahti.fi/~hag/share/MyGame2.exe
This is now little different... for starters, cpu stays in good 0% and gameplay is smooth. FPS is however behaving odd but not bad at all; it stays at either exactly 500 or 527 (nothing between, under or above) and when it stays there it does that for 15 sec or something random, i think when it stops to 527 it tends to stay there longer or persistently.

... and like this matters, it run not perfectly but a good 200+ fps while running world of warcraft in crowded city :)

FusionWolf
30-09-2009, 03:38 PM
Yes, that's how it is designed to work currently. :yes:

I uncommented that Sleep(1) routine at the timer update method so it drops the maximum framerates around to 500 or so.

Also I changed the way how frames per second is calculated and that's the reason for it's behavior. Calculation is done only once in a second so, in theory it could be change *dadaa* once in a second ;D, but as you noticed it should not, and doesn't do that. That's why it keeps it in one reading and then may change it to another after a while. ;)

I'm still wondering those Pauls 55 or so frame rate, because I get near 400 even with old 1,6GHz Duron and 9600 Radeon, but if it runs smoothly that doesn't really matter. ;)

But I will explore more about timing and I will develop more sophisticated version after the 'game' is up and running. Until then let's keep this one. :)

edit: Ouh, forgot to mention... thank's guys (I assume you are guys ;D) for your very valuable feedback. :yes:

FusionWolf
04-10-2009, 01:20 AM
This story continues here:
http://www.pascalgamedevelopment.com/forum/index.php?topic=5967.0