Please help with Blitz Plus Benchmarks

Miscellaneous Forums/General Discussion/Please help with Blitz Plus Benchmarks

Hi, I've recently been getting in a pickle with Blitz Plus as I've been trying out various different draw routines to see which are the fastest, especially on slow machines.

Please help me by downloading this file and running it:

http://www.jbcomputersolutions.com/misc/bench.zip

It will auto save a .bmp screenshot which you could convert to .png (preferably) or .jpg and upload.

[EDIT] It now also saves a file called Results.txt, you may find it better to copy and paste the text into your post.

Here's mine:



Please also post your specs e.g. CPU, RAM, Video Card, OS. (mine are in my sig ;-)

This info is vital to all newbie (and possibly experienced) BlitzPlus programmers! For example, never use ReadPixelFast on the BackBuffer or a Dynamic Image (held on video card) as it is hellishly slow. The same command on a Managed Image (in RAM) is 24 times faster! Note that WritePixel fast is pretty much the same on all.

DrawBlock is the same speed as CopyRect so that should put to rest the legend that CopyRect is faster, it's not.

There is a very important point hidden in the stats which has been giving me grief due to my triple buffer system. Basically the lines that contain "changed" mean I used Plot to draw a *single* black pixel on the image. Note how sending a changed managed imaged (in RAM) to the backbuffer or a dynamic image (video card) actually takes twice as long as sending an unchanged image! This is only one pixel we are talking about! If you draw a whole screenfull of pixels it still takes the same speed! There is some inherent delay in sending a changed RAM Image to the Video Card, if the image is unchanged it's twice as fast, perhaps due to caching.

The final point to note is that GrabImage to a managed image is stinky slow when used on the backbuffer or a dynamic image. Also it is the same speed as DrawBlock and CopyRect.

So to summarise, don't read from the video card, only write to it. DrawBlock, CopyRect and GrabImage are the same speed. Sending a changed managed image (RAM) to the video card is annoyingly slower than and unchanged one (or a dynamic one) for some reason.

The important point to all this is if your times go above 16.7ms this means that it will take greater than 1 frame to draw the screen on a 60Hz refresh rate resulting in dropped frames! This would be bad on slower PCs. Of course if you run at 85Hz, the times only need to go above 11.8ms and you drop frames.

Please post soon, I really want to see you results esp. on slower/older PCs with normal (non-3D) graphics cards.

Thanks in advance.

Here you go. Why not have the data dumped into a text or even XML file? Surely it'd be easier to compile your statistics that way?



Why not have the data dumped into a text or even XML file? Surely it'd be easier to compile your statistics that way?


Yup, and easier on people's bandwidth :)





AMD Athlon XP 2500+ 1.8 GHz
1280 MB RAM
Radeon 9600 Pro, DirectX 9.0c

Weird way of showing stats, but....



Specs here were, Laptop - Celeron 1.1ghz CPU - 512MB RAM Joyous onboard 8mb Intel 830 Gfx. Done while spooling Yahoo radio in the background, so that may of affected a few things.



You may want to consider doing a version that outputs a textfile that people can copy/paste... After all, many people don't have webspace where they can post an image for you, plus it would be a lot easier for yourself to compare the results that way.

anyway, here it goes:

Empty for loop x 100					149ms 	= 1.49 each
Read pixel fast from backbuffer x 10			1700ms	= 170.0 each
Read pixel fast from dynamic image x 10			1697ms	= 169.7 each
Read pixel fast from managed image x 10			131ms	= 13.1 each
Write pixel fast to backbuffer x 10			157ms	= 15.7 each
Write pixel fast to dynamic image x 10			145ms	= 14.5 each
Write pixel fast to managed image x 10			122ms	= 12.2 each
Drawblock dynamic image to backbuffer x 10		44ms	= 4.4 each
Drawblock managed image to backbuffer x 10		46ms	= 4.6 each
Drawblock changed dynamic image to backbuffer x 10	45ms	= 4.5 each
Drawblock changed managed image to backbuffer x 10	91ms	= 9.1 each
copyrect dynamic image to backbuffer x 10		45ms	= 4.5 each
copyrect managed image to backbuffer x 10		45ms	= 4.5 each
copyrect changed dynamic image to backbuffer x 10	46ms	= 4.6 each
copyrect changed managed image to backbuffer x 10	95ms	= 9.5 each
copyrect dynamic image to dynamic image x 10		33ms	= 3.3 each
copyrect managed image to managed image x 10		46ms	= 4.6 each
copyrect dynamic image to managed image x 10		1640ms	= 164.0 each
copyrect managed image to dynamic image x 10		33ms	= 3.3 each
copyrect changed DI to MI x 10				1645ms	= 164.5 each
copyrect MI to DI x 10					79ms	= 7.9 each
Grabimage (dynamic) from backbuffer x 10		32ms	= 3.2 each
Grabimage (managed) from backbuffer x 10		1674ms	= 167.4 each
Grabimage (dynamic) from DI x 10			34ms	= 3.4 each
Grabimage (managed) from MI x 10			46ms	= 4.6 each
Grabimage (dynamic) from MI x 10			33ms	= 3.3 each
Grabimage (managed) from DI x 10			1636ms	= 163.6 each

80+ WPM typing skills are good for something after all. ;-)

Hmm... surprising to see how much faster my 32bit 2800+ is than Pertubatio's AMD64 3000+ on the readpixel/grabimage tests.

Thanks ALL for your help! Great.

TeaVirus: Yeah you are right about the text file, but luckily the png is only 14K.

xlsior: lol, hope you didn't make a mistake! But yeah, your Backbuffer to RAM is the fastest here and I've got a 3.2GHz with 9800XT ... I want my money back!

some of you have very slow For loop speeds! Seem to be on the Athlons, maybe you started the app quickly and the system was still doing some disk thrashing. A reasonable component of the Read/WritePixel Fast benchmarks is actually the For loop.

Qube: Your laptop stats are very interesting, basically a Blitz Plus triple buffer system would only run at 30FPS on it and a normal double buffer system would run into problems if it drew too many things.

Indiepath: specs?

80+ WPM typing skills are good for something after all. ;-)


You don't have OCR then?

OK, I've upload a new version that outputs a Results.txt file, this should make it a whole bunch easier for people to post specs. Any low specs I am very interested in.

Here's my Laptop that I did with the pre-text version:



It's a P2.4, 512MB, XP SP2 with onboard video card (non3D). Notice how fast the video card is! Maybe 3D ones aren't optimised for basic 2D operations!

Check out this beast: P166, 48MB RAM, S3 Trio64, Win98 SE. It can only run in 16 bit colour mode:

Empty For Loop x 100 2646ms = 26.46 each
Read Pixel Fast From BackBuffer x 10 3328ms = 332.8 each
Read Pixel Fast From Dynamic Image x 10 3446ms = 344.6 each
Read Pixel Fast From Managed Image x 10 3648ms = 364.8 each
Write Pixel Fast To BackBuffer x 10 4890ms = 489.0 each
Write Pixel Fast To Dynamic Image x 10 5051ms = 505.1 each
Write Pixel Fast To Managed Image x 10 5833ms = 583.3 each
DrawBlock Dynamic Image to BackBuffer x 10 493ms = 49.3 each
DrawBlock Managed Image to BackBuffer x 10 913ms = 91.3 each
DrawBlock changed Dynamic Image to BackBuffer x 10 487ms = 48.7 each
DrawBlock changed Managed Image to BackBuffer x 10 4029ms = 402.9 each
CopyRect Dynamic Image to BackBuffer x 10 481ms = 48.1 each
CopyRect Managed Image to BackBuffer x 10 922ms = 92.2 each
CopyRect changed Dynamic Image to BackBuffer x 10 531ms = 53.1 each
CopyRect changed Managed Image to BackBuffer x 10 4033ms = 403.3 each
CopyRect Dynamic Image to Dynamic Image x 10 552ms = 55.2 each
CopyRect Managed Image to Managed Image x 10 819ms = 81.9 each
CopyRect Dynamic Image to Managed Image x 10 4214ms = 421.4 each
CopyRect Managed Image to Dynamic Image x 10 976ms = 97.6 each
CopyRect changed DI to MI x 10 4215ms = 421.5 each
CopyRect changed MI to DI x 10 4166ms = 416.6 each
GrabImage (dynamic) from BackBuffer x 10 494ms = 49.4 each
GrabImage (managed) from BackBuffer x 10 4128ms = 412.8 each
GrabImage (dynamic) from DI x 10 524ms = 52.4 each
GrabImage (managed) from MI x 10 808ms = 80.8 each
GrabImage (dynamic) from MI x 10 993ms = 99.3 each
GrabImage (managed) from DI x 10 4210ms = 421.0 each

It's so bad that it takes half a second to WritePixel an 800x600 screen to the backbuffer. The absolute best you could get out of a double buffer system on this is 20FPS.

Check out this example code:

Global ScreenHeight = 600
Global BitDepth = 32
Global multiplier = 100

Graphics (ScreenWidth, ScreenHeight, BitDepth, 0)

Global Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 1)

Text 0,0,"press any key"
Flip
WaitKey

st = MilliSecs()
For n = 1 To multiplier
	SetBuffer ImageBuffer(Temp)
	Color 255,255,0
	Plot 100,100
	SetBuffer BackBuffer()
	CopyRect(100,100,1,1,100,100,ImageBuffer(Temp))
Next
endt = MilliSecs() - st
Flip
Text 0,20,"x "+multiplier+ " = " + endt+"ms" + " = " + endt/(multiplier*1.0) + "ms each"
Text 0,40,"press any key"
Flip
FreeImage Temp
WaitKey


on my PC it takes 3ms (per loop iteration) just to write a pixel onto an image in RAM and then copyrect it to the backbuffer. On slower machines this would go over the refresh rate easily and thus drop the FPS.

In the above code I tried replacing the inside of the lop with:

 LockBuffer ImageBuffer(Temp)
 WritePixelFast(100,100,255,ImageBuffer(Temp))
 UnlockBuffer ImageBuffer(Temp)
 LockBuffer BackBuffer()
 CopyRect(100,100,1,1,100,100,ImageBuffer(Temp))
 UnlockBuffer BackBuffer()

and also
 LockBuffer ImageBuffer(Temp)
 b = LockedPixels(ImageBuffer(Temp))
 PokeInt(b,0,$ffffff)
 UnlockBuffer ImageBuffer(Temp)
 SetBuffer BackBuffer()
 LockBuffer BackBuffer()
 CopyRect(0,0,1,1,100,100,ImageBuffer(Temp))
 UnlockBuffer BackBuffer()


I know you don't need LockBuffer around the CopyRect but it's the same speed with and without it, I just wanted to avoid people suggesting it as it makes no difference, in fact CopyRect doesn't even work when the backbuffer is locked.

I've tried pretty much everything now except for making a bank and my own drawing routines and then memcopying the bank to the video buffer. I could be "just around the corner" from the answer or I could spend EONS on this cr*p. That's why I figured on cutting my losses and going to BMax ASAP.

Unless anyone has a miracle cure? Any takers?

Empty For Loop x 100                                72ms     = 0.72 each
Read Pixel Fast From BackBuffer x 10                1296ms   = 129.6 each
Read Pixel Fast From Dynamic Image x 10             1142ms   = 114.2 each
Read Pixel Fast From Managed Image x 10             117ms    = 11.7 each
Write Pixel Fast To BackBuffer x 10                 148ms    = 14.8 each
Write Pixel Fast To Dynamic Image x 10              137ms    = 13.7 each
Write Pixel Fast To Managed Image x 10              158ms    = 15.8 each
DrawBlock Dynamic Image to BackBuffer x 10          44ms     = 4.4 each
DrawBlock Managed Image to BackBuffer x 10          44ms     = 4.4 each
DrawBlock changed Dynamic Image to BackBuffer x 10  44ms     = 4.4 each
DrawBlock changed Managed Image to BackBuffer x 10  84ms     = 8.4 each
CopyRect Dynamic Image to BackBuffer x 10           42ms     = 4.2 each
CopyRect Managed Image to BackBuffer x 10           45ms     = 4.5 each
CopyRect changed Dynamic Image to BackBuffer x 10   46ms     = 4.6 each
CopyRect changed Managed Image to BackBuffer x 10   86ms     = 8.6 each
CopyRect Dynamic Image to Dynamic Image x 10        27ms     = 2.7 each
CopyRect Managed Image to Managed Image x 10        41ms     = 4.1 each
CopyRect Dynamic Image to Managed Image x 10        1128ms   = 112.8 each
CopyRect Managed Image to Dynamic Image x 10        35ms     = 3.5 each
CopyRect changed DI to MI x 10                      1120ms   = 112.0 each
CopyRect changed MI to DI x 10                      73ms     = 7.3 each
GrabImage (dynamic) from BackBuffer x 10            33ms     = 3.3 each
GrabImage (managed) from BackBuffer x 10            1191ms   = 119.1 each
GrabImage (dynamic) from DI x 10                    29ms     = 2.9 each
GrabImage (managed) from MI x 10                    38ms     = 3.8 each
GrabImage (dynamic) from MI x 10                    37ms     = 3.7 each
GrabImage (managed) from DI x 10                    1100ms   = 110.0 each


Thanks Adren Software, some good speeds there.

Empty For Loop x 100                                147ms    = 1.47 each
Read Pixel Fast From BackBuffer x 10                8300ms   = 830.0 each
Read Pixel Fast From Dynamic Image x 10             8290ms   = 829.0 each
Read Pixel Fast From Managed Image x 10             92ms     = 9.2 each
Write Pixel Fast To BackBuffer x 10                 119ms    = 11.9 each
Write Pixel Fast To Dynamic Image x 10              123ms    = 12.3 each
Write Pixel Fast To Managed Image x 10              97ms     = 9.7 each
DrawBlock Dynamic Image to BackBuffer x 10          22ms     = 2.2 each
DrawBlock Managed Image to BackBuffer x 10          25ms     = 2.5 each
DrawBlock changed Dynamic Image to BackBuffer x 10  23ms     = 2.3 each
DrawBlock changed Managed Image to BackBuffer x 10  58ms     = 5.8 each
CopyRect Dynamic Image to BackBuffer x 10           23ms     = 2.3 each
CopyRect Managed Image to BackBuffer x 10           26ms     = 2.6 each
CopyRect changed Dynamic Image to BackBuffer x 10   23ms     = 2.3 each
CopyRect changed Managed Image to BackBuffer x 10   58ms     = 5.8 each
CopyRect Dynamic Image to Dynamic Image x 10        24ms     = 2.4 each
CopyRect Managed Image to Managed Image x 10        18ms     = 1.8 each
CopyRect Dynamic Image to Managed Image x 10        8224ms   = 822.4 each
CopyRect Managed Image to Dynamic Image x 10        28ms     = 2.8 each
CopyRect changed DI to MI x 10                      8212ms   = 821.2 each
CopyRect changed MI to DI x 10                      59ms     = 5.9 each
GrabImage (dynamic) from BackBuffer x 10            23ms     = 2.3 each
GrabImage (managed) from BackBuffer x 10            8214ms   = 821.4 each
GrabImage (dynamic) from DI x 10                    24ms     = 2.4 each
GrabImage (managed) from MI x 10                    20ms     = 2.0 each
GrabImage (dynamic) from MI x 10                    28ms     = 2.8 each
GrabImage (managed) from DI x 10                    8213ms   = 821.3 each


Edit: Why are the "Read Pixel Fast From BackBuffer x 10" slower than even the onboard cards?

wow, yeah that is slow, seems you card is totally normal/fast at writing but horrid at reading, I can't say why, sorry.

Athlon 1Ghz, GeForce2 GTS 32MB, 256MB RAM, Win98SE.

This is with all my usual background tasks runnning (firewall, virus scanner, net connection etc.) which will probably have an impact on the results. That's my excuse, anyway. :)

Empty For Loop x 100                                204ms    = 2.04 each
Read Pixel Fast From BackBuffer x 10                3194ms   = 319.4 each
Read Pixel Fast From Dynamic Image x 10             3217ms   = 321.7 each
Read Pixel Fast From Managed Image x 10             298ms    = 29.8 each
Write Pixel Fast To BackBuffer x 10                 267ms    = 26.7 each
Write Pixel Fast To Dynamic Image x 10              247ms    = 24.7 each
Write Pixel Fast To Managed Image x 10              293ms    = 29.3 each
DrawBlock Dynamic Image to BackBuffer x 10          25ms     = 2.5 each
DrawBlock Managed Image to BackBuffer x 10          38ms     = 3.8 each
DrawBlock changed Dynamic Image to BackBuffer x 10  25ms     = 2.5 each
DrawBlock changed Managed Image to BackBuffer x 10  146ms    = 14.6 each
CopyRect Dynamic Image to BackBuffer x 10           25ms     = 2.5 each
CopyRect Managed Image to BackBuffer x 10           37ms     = 3.7 each
CopyRect changed Dynamic Image to BackBuffer x 10   26ms     = 2.6 each
CopyRect changed Managed Image to BackBuffer x 10   150ms    = 15.0 each
CopyRect Dynamic Image to Dynamic Image x 10        25ms     = 2.5 each
CopyRect Managed Image to Managed Image x 10        73ms     = 7.3 each
CopyRect Dynamic Image to Managed Image x 10        3098ms   = 309.8 each
CopyRect Managed Image to Dynamic Image x 10        38ms     = 3.8 each
CopyRect changed DI to MI x 10                      3101ms   = 310.1 each
CopyRect changed MI to DI x 10                      147ms    = 14.7 each
GrabImage (dynamic) from BackBuffer x 10            25ms     = 2.5 each
GrabImage (managed) from BackBuffer x 10            3103ms   = 310.3 each
GrabImage (dynamic) from DI x 10                    25ms     = 2.5 each
GrabImage (managed) from MI x 10                    73ms     = 7.3 each
GrabImage (dynamic) from MI x 10                    38ms     = 3.8 each
GrabImage (managed) from DI x 10                    3095ms   = 309.5 each


Thanks Big10, seems like your machine does OK actually.

Even more all over the place results than aeiou's:
Empty For Loop x 100                                104ms    = 1.04 each
Read Pixel Fast From BackBuffer x 10                8615ms   = 861.5 each
Read Pixel Fast From Dynamic Image x 10             8594ms   = 859.4 each
Read Pixel Fast From Managed Image x 10             117ms    = 11.7 each
Write Pixel Fast To BackBuffer x 10                 125ms    = 12.5 each
Write Pixel Fast To Dynamic Image x 10              125ms    = 12.5 each
Write Pixel Fast To Managed Image x 10              124ms    = 12.4 each
DrawBlock Dynamic Image to BackBuffer x 10          30ms     = 3.0 each
DrawBlock Managed Image to BackBuffer x 10          24ms     = 2.4 each
DrawBlock changed Dynamic Image to BackBuffer x 10  19ms     = 1.9 each
DrawBlock changed Managed Image to BackBuffer x 10  59ms     = 5.9 each
CopyRect Dynamic Image to BackBuffer x 10           17ms     = 1.7 each
CopyRect Managed Image to BackBuffer x 10           26ms     = 2.6 each
CopyRect changed Dynamic Image to BackBuffer x 10   16ms     = 1.6 each
CopyRect changed Managed Image to BackBuffer x 10   59ms     = 5.9 each
CopyRect Dynamic Image to Dynamic Image x 10        19ms     = 1.9 each
CopyRect Managed Image to Managed Image x 10        29ms     = 2.9 each
CopyRect Dynamic Image to Managed Image x 10        8456ms   = 845.6 each
CopyRect Managed Image to Dynamic Image x 10        27ms     = 2.7 each
CopyRect changed DI to MI x 10                      8482ms   = 848.2 each
CopyRect changed MI to DI x 10                      62ms     = 6.2 each
GrabImage (dynamic) from BackBuffer x 10            17ms     = 1.7 each
GrabImage (managed) from BackBuffer x 10            8444ms   = 844.4 each
GrabImage (dynamic) from DI x 10                    20ms     = 2.0 each
GrabImage (managed) from MI x 10                    30ms     = 3.0 each
GrabImage (dynamic) from MI x 10                    26ms     = 2.6 each
GrabImage (managed) from DI x 10                    8445ms   = 844.5 each


Running on Athlon64 3000, Windows XP SP2, 512mb ram, XFX GeForce 6600 256mb.

Empty For Loop x 100                                106ms    = 1.06 each
Read Pixel Fast From BackBuffer x 10                3744ms   = 374.4 each
Read Pixel Fast From Dynamic Image x 10             3741ms   = 374.1 each
Read Pixel Fast From Managed Image x 10             96ms     = 9.6 each
Write Pixel Fast To BackBuffer x 10                 116ms    = 11.6 each
Write Pixel Fast To Dynamic Image x 10              119ms    = 11.9 each
Write Pixel Fast To Managed Image x 10              97ms     = 9.7 each
DrawBlock Dynamic Image to BackBuffer x 10          30ms     = 3.0 each
DrawBlock Managed Image to BackBuffer x 10          32ms     = 3.2 each
DrawBlock changed Dynamic Image to BackBuffer x 10  30ms     = 3.0 each
DrawBlock changed Managed Image to BackBuffer x 10  66ms     = 6.6 each
CopyRect Dynamic Image to BackBuffer x 10           30ms     = 3.0 each
CopyRect Managed Image to BackBuffer x 10           32ms     = 3.2 each
CopyRect changed Dynamic Image to BackBuffer x 10   31ms     = 3.1 each
CopyRect changed Managed Image to BackBuffer x 10   65ms     = 6.5 each
CopyRect Dynamic Image to Dynamic Image x 10        32ms     = 3.2 each
CopyRect Managed Image to Managed Image x 10        23ms     = 2.3 each
CopyRect Dynamic Image to Managed Image x 10        3677ms   = 367.7 each
CopyRect Managed Image to Dynamic Image x 10        34ms     = 3.4 each
CopyRect changed DI to MI x 10                      3682ms   = 368.2 each
CopyRect changed MI to DI x 10                      66ms     = 6.6 each
GrabImage (dynamic) from BackBuffer x 10            31ms     = 3.1 each
GrabImage (managed) from BackBuffer x 10            3680ms   = 368.0 each
GrabImage (dynamic) from DI x 10                    32ms     = 3.2 each
GrabImage (managed) from MI x 10                    22ms     = 2.2 each
GrabImage (dynamic) from MI x 10                    35ms     = 3.5 each
GrabImage (managed) from DI x 10                    3680ms   = 368.0 each


Wow... Now I now how to do a [code] tag... Is there any info on other tags I can use?

Empty For Loop x 100                                107ms    = 1.07 each
Read Pixel Fast From BackBuffer x 10                3134ms   = 313.4 each
Read Pixel Fast From Dynamic Image x 10             2778ms   = 277.8 each
Read Pixel Fast From Managed Image x 10             141ms    = 14.1 each
Write Pixel Fast To BackBuffer x 10                 159ms    = 15.9 each
Write Pixel Fast To Dynamic Image x 10              145ms    = 14.5 each
Write Pixel Fast To Managed Image x 10              122ms    = 12.2 each
DrawBlock Dynamic Image to BackBuffer x 10          46ms     = 4.6 each
DrawBlock Managed Image to BackBuffer x 10          47ms     = 4.7 each
DrawBlock changed Dynamic Image to BackBuffer x 10  45ms     = 4.5 each
DrawBlock changed Managed Image to BackBuffer x 10  83ms     = 8.3 each
CopyRect Dynamic Image to BackBuffer x 10           47ms     = 4.7 each
CopyRect Managed Image to BackBuffer x 10           47ms     = 4.7 each
CopyRect changed Dynamic Image to BackBuffer x 10   46ms     = 4.6 each
CopyRect changed Managed Image to BackBuffer x 10   83ms     = 8.3 each
CopyRect Dynamic Image to Dynamic Image x 10        32ms     = 3.2 each
CopyRect Managed Image to Managed Image x 10        20ms     = 2.0 each
CopyRect Dynamic Image to Managed Image x 10        2735ms   = 273.5 each
CopyRect Managed Image to Dynamic Image x 10        32ms     = 3.2 each
CopyRect changed DI to MI x 10                      2726ms   = 272.6 each
CopyRect changed MI to DI x 10                      70ms     = 7.0 each
GrabImage (dynamic) from BackBuffer x 10            31ms     = 3.1 each
GrabImage (managed) from BackBuffer x 10            2742ms   = 274.2 each
GrabImage (dynamic) from DI x 10                    31ms     = 3.1 each
GrabImage (managed) from MI x 10                    20ms     = 2.0 each
GrabImage (dynamic) from MI x 10                    33ms     = 3.3 each
GrabImage (managed) from DI x 10                    2729ms   = 272.9 each


Anatoly : What are the forum codes?

Empty For Loop x 100                                99ms     = 0.99 each
Read Pixel Fast From BackBuffer x 10                3256ms   = 325.6 each
Read Pixel Fast From Dynamic Image x 10             3222ms   = 322.2 each
Read Pixel Fast From Managed Image x 10             121ms    = 12.1 each
Write Pixel Fast To BackBuffer x 10                 171ms    = 17.1 each
Write Pixel Fast To Dynamic Image x 10              148ms    = 14.8 each
Write Pixel Fast To Managed Image x 10              119ms    = 11.9 each
DrawBlock Dynamic Image to BackBuffer x 10          48ms     = 4.8 each
DrawBlock Managed Image to BackBuffer x 10          56ms     = 5.6 each
DrawBlock changed Dynamic Image to BackBuffer x 10  54ms     = 5.4 each
DrawBlock changed Managed Image to BackBuffer x 10  93ms     = 9.3 each
CopyRect Dynamic Image to BackBuffer x 10           54ms     = 5.4 each
CopyRect Managed Image to BackBuffer x 10           56ms     = 5.6 each
CopyRect changed Dynamic Image to BackBuffer x 10   56ms     = 5.6 each
CopyRect changed Managed Image to BackBuffer x 10   92ms     = 9.2 each
CopyRect Dynamic Image to Dynamic Image x 10        35ms     = 3.5 each
CopyRect Managed Image to Managed Image x 10        34ms     = 3.4 each
CopyRect Dynamic Image to Managed Image x 10        3231ms   = 323.1 each
CopyRect Managed Image to Dynamic Image x 10        40ms     = 4.0 each
CopyRect changed DI to MI x 10                      3231ms   = 323.1 each
CopyRect changed MI to DI x 10                      76ms     = 7.6 each
GrabImage (dynamic) from BackBuffer x 10            40ms     = 4.0 each
GrabImage (managed) from BackBuffer x 10            3244ms   = 324.4 each
GrabImage (dynamic) from DI x 10                    37ms     = 3.7 each
GrabImage (managed) from MI x 10                    35ms     = 3.5 each
GrabImage (dynamic) from MI x 10                    40ms     = 4.0 each
GrabImage (managed) from DI x 10                    3230ms   = 323.0 each

Athlon XP 3000+ with 1 gig RAM, 128 meg Radeon 9600 Pro, XP Pro SP 2

Even more all over the place results than aeiou's:


Looks like it might be a GeForce 6600 problem

Empty For Loop x 100                                82ms     = 0.82 each
Read Pixel Fast From BackBuffer x 10                3048ms   = 304.8 each
Read Pixel Fast From Dynamic Image x 10             3036ms   = 303.6 each
Read Pixel Fast From Managed Image x 10             87ms     = 8.7 each
Write Pixel Fast To BackBuffer x 10                 100ms    = 10.0 each
Write Pixel Fast To Dynamic Image x 10              99ms     = 9.9 each
Write Pixel Fast To Managed Image x 10              89ms     = 8.9 each
DrawBlock Dynamic Image to BackBuffer x 10          15ms     = 1.5 each
DrawBlock Managed Image to BackBuffer x 10          17ms     = 1.7 each
DrawBlock changed Dynamic Image to BackBuffer x 10  15ms     = 1.5 each
DrawBlock changed Managed Image to BackBuffer x 10  46ms     = 4.6 each
CopyRect Dynamic Image to BackBuffer x 10           14ms     = 1.4 each
CopyRect Managed Image to BackBuffer x 10           18ms     = 1.8 each
CopyRect changed Dynamic Image to BackBuffer x 10   14ms     = 1.4 each
CopyRect changed Managed Image to BackBuffer x 10   45ms     = 4.5 each
CopyRect Dynamic Image to Dynamic Image x 10        15ms     = 1.5 each
CopyRect Managed Image to Managed Image x 10        19ms     = 1.9 each
CopyRect Dynamic Image to Managed Image x 10        3008ms   = 300.8 each
CopyRect Managed Image to Dynamic Image x 10        18ms     = 1.8 each
CopyRect changed DI to MI x 10                      3007ms   = 300.7 each
CopyRect changed MI to DI x 10                      45ms     = 4.5 each
GrabImage (dynamic) from BackBuffer x 10            13ms     = 1.3 each
GrabImage (managed) from BackBuffer x 10            2995ms   = 299.5 each
GrabImage (dynamic) from DI x 10                    14ms     = 1.4 each
GrabImage (managed) from MI x 10                    17ms     = 1.7 each
GrabImage (dynamic) from MI x 10                    18ms     = 1.8 each
GrabImage (managed) from DI x 10                    2998ms   = 299.8 each


Big&: some very quick CPU based times there, I'm sure my game would run on your PC ;-)

It seems it doesn't matter how fast your machine is, you're not going to get under 300ms for some of those things. Must be some sort of AGP/PCIE bandwidth thing, surely?

Looks like it might be a GeForce 6600 problem

Hmm, 3D games run just dandy, so I guess 6600's have flaws when it comes to 2D manipulation.

My laptop had the best times for getting data from the backbuffer and it's not a 3D card, must be well optimised for 2D operations.

Oh yeh look at that. So cards these days are actually taking steps backwards. Great.

Why did you test only dynamic images and managed images when there are also scratch images?

Dynamic is stored only in vram, managed is stored in both vram and regular ram, and scratch is stored only in regular ram.

I suspect scratch might get the same results as managed, but the only way to be sure is to test.

From Big&'s results:

Read Pixel Fast From BackBuffer x 10                3048ms   = 304.8 each VIDRAM -> RAM
Read Pixel Fast From Dynamic Image x 10             3036ms   = 303.6 each VIDRAM -> RAM
Read Pixel Fast From Managed Image x 10             87ms     = 8.7 each RAM -> RAM
Write Pixel Fast To BackBuffer x 10                 100ms    = 10.0 each RAM -> VIDRAM
Write Pixel Fast To Dynamic Image x 10              99ms     = 9.9 each RAM -> VIDRAM
Write Pixel Fast To Managed Image x 10              89ms     = 8.9 each RAM -> VIDRAM + RAM (10ms faster?  huh?)
DrawBlock Dynamic Image to BackBuffer x 10          15ms     = 1.5 each VIDRAM -> VIDRAM
DrawBlock Managed Image to BackBuffer x 10          17ms     = 1.7 each VIDRAM -> VIDRAM
DrawBlock changed Dynamic Image to BackBuffer x 10  15ms     = 1.5 each VIDRAM -> VIDRAM
DrawBlock changed Managed Image to BackBuffer x 10  46ms     = 4.6 each VIDRAM? -> VIDRAM
CopyRect Dynamic Image to BackBuffer x 10           14ms     = 1.4 each VIDRAM -> VIDRAM
CopyRect Managed Image to BackBuffer x 10           18ms     = 1.8 each VIDRAM -> VIDRAM
CopyRect changed Dynamic Image to BackBuffer x 10   14ms     = 1.4 each VIDRAM -> VIDRAM
CopyRect changed Managed Image to BackBuffer x 10   45ms     = 4.5 each VIDRAM? -> VIDRAM
CopyRect Dynamic Image to Dynamic Image x 10        15ms     = 1.5 each VIDRAM -> VIDRAM
CopyRect Managed Image to Managed Image x 10        19ms     = 1.9 each RAM (+VIDRAM?)-> RAM (+VIDRAM?)
CopyRect Dynamic Image to Managed Image x 10        3008ms   = 300.8 each VIDRAM -> VIDRAM + RAM
CopyRect Managed Image to Dynamic Image x 10        18ms     = 1.8 each VIDRAM -> VIDRAM
CopyRect changed DI to MI x 10                      3007ms   = 300.7 each VIDRAM -> VIDRAM + RAM
CopyRect changed MI to DI x 10                      45ms     = 4.5 each VIDRAM -> VIDRAM (dunno why it's 45ms)
GrabImage (dynamic) from BackBuffer x 10            13ms     = 1.3 each VIDRAM -> VIDRAM
GrabImage (managed) from BackBuffer x 10            2995ms   = 299.5 each VIDRAM -> VIDRAM + RAM
GrabImage (dynamic) from DI x 10                    14ms     = 1.4 each VIDRAM -> VIDRAM
GrabImage (managed) from MI x 10                    17ms     = 1.7 each RAM (+VIDRAM?) -> RAM (+VIDRAM?)
GrabImage (dynamic) from MI x 10                    18ms     = 1.8 each VIDRAM -> VIDRAM
GrabImage (managed) from DI x 10                    2998ms   = 299.8 each VIDRAM -> VIDRAM + RAM


So as you can see, moving data from vidram to ram is the main problem here, but there's a few weird cases like the 45ms above where I'm not sure what causes the extra delay.

Oddly, moving data from ram to vidram is much faster than moving it the other way, but still realtively slow, which was to be expected. I don't know why this would be, but it seems obvious it's a bug of some kind.

No wait, cancel that, those are writepixels being used there and there's only 10 of them. No ram - > vidram test was done unless changing the managed image counts, and I don't think it does because I think the change takes place immediately before the loop to test the copy speed, so the delay would be there, not in the loop. This is why you should have tested scratch images because they are only in ram.

sswift: I tested scratch and it was the same as managed image so I left it off. How can managed be in VRAM and RAM at the same time unless there's a copy in each. Actually my theory is there is a copy in each and if you reshow (on backbuffer) or resuse the image without modifications it uses the VRAM copy and if you modify it, it get's modified in RAM and of course needs to be copied to VRAM again. Managed images are very fast for doing ReadPixelFast on for visual effects, whereas dynamic ones are not. All the 45Ms cases are "Changed" Managed images i.e. the change is made in RAM and copied to VRAM and this is the delay. That's my theory anyway. It meant that a triple buffer system so the effects can be applied in the 3rd buffer (RAM copy) is actually too slow due to the copy time when it moves over to VRAM. If my theory is wrong then I'll eat my digitial hat, no actually, I'd like to hear from someone that REALLY knows.

sswift: It's not doing 10 writepixels it's doing 800x600 of them 10 times over! All my "changed" stats actually write a single pixel *inside* the loop not outside, that's what causes the delay. Remove the Plot and the time drops again.

I'll post the source.

hang on ...

;/////////////////////////////////////
;Bench V0.1 Jake Birkett  Mon 07/11/05
;/////////////////////////////////////

Global ScreenWidth = 800
Global ScreenHeight = 600
Global BitDepth = 32
Global multiplier = 100

Graphics (ScreenWidth, ScreenHeight, BitDepth, 0)

Global Results = WriteFile("Results.txt")

Global ly = 0
Global gap = 10
Color 0,255,255
Text 0,ly,"Blitz Plus Bench V0.1 (c) 2005 Jake Birkett"
ly=ly+gap
Text 0,ly,"-------------------------------------------"
ly=ly+gap*2
Color 255,255,0
Text 0,ly,"width="+ScreenWidth+" height="+ScreenHeight+" depth="+BitDepth
ly=ly+gap*2
Color 0,255,0
Text 0,ly,"<press any key to start>"
ly=ly+gap*2
Flip
WaitKey()

Func(1, "Empty For Loop", 100)
Func(2, "Read Pixel Fast From BackBuffer", 10)
Func(3, "Read Pixel Fast From Dynamic Image", 10)
Func(4, "Read Pixel Fast From Managed Image", 10)
Func(5, "Write Pixel Fast To BackBuffer", 10)
Func(6, "Write Pixel Fast To Dynamic Image", 10)
Func(7, "Write Pixel Fast To Managed Image", 10)
Func(8, "DrawBlock Dynamic Image to BackBuffer", 10)
Func(9, "DrawBlock Managed Image to BackBuffer", 10)
Func(10, "DrawBlock changed Dynamic Image to BackBuffer", 10)
Func(11, "DrawBlock changed Managed Image to BackBuffer", 10)
Func(12, "CopyRect Dynamic Image to BackBuffer", 10)
Func(13, "CopyRect Managed Image to BackBuffer", 10)
Func(14, "CopyRect changed Dynamic Image to BackBuffer", 10)
Func(15, "CopyRect changed Managed Image to BackBuffer", 10)
Func(16, "CopyRect Dynamic Image to Dynamic Image", 10)
Func(17, "CopyRect Managed Image to Managed Image", 10)
Func(18, "CopyRect Dynamic Image to Managed Image", 10)
Func(19, "CopyRect Managed Image to Dynamic Image", 10)
Func(20, "CopyRect changed DI to MI", 10)
Func(21, "CopyRect changed MI to DI", 10)
Func(22, "GrabImage (dynamic) from BackBuffer", 10)
Func(23, "GrabImage (managed) from BackBuffer", 10)
Func(24, "GrabImage (dynamic) from DI", 10)
Func(25, "GrabImage (managed) from MI", 10)
Func(26, "GrabImage (dynamic) from MI", 10)
Func(27, "GrabImage (managed) from DI", 10)

CloseFile(Results)

gfxGrab = CreateImage(ScreenWidth, ScreenHeight, 1, 1)
Flip
GrabImage gfxGrab,0,0
Flip
SaveImage gfxGrab, CurrentDir()+"screenshot.bmp"
FreeImage gfxGrab
	
Flip
Color 255,255,255
ly=ly+gap
Text 0,ly,"Screenshot saved"
ly=ly+gap*2
Color 0,255,0
Text 0,ly,"<press any key to exit>"
Flip
FlushKeys ;doesn't seem to work
WaitKey()

Function Func(num%, name$, m%)
	multiplier = m
	Flip
	Color 255,255,255
	Text 0,ly,name$ + " x "+multiplier
	Flip
	st = MilliSecs()
	Select num
		Case 1 EmptyForLoop()	
		Case 2 ReadPixelFastFromBackBuffer()	
		Case 3 ReadPixelFastFromDI()	
		Case 4 ReadPixelFastFromMI()	
		Case 5 WritePixelFastToBackBuffer()	
		Case 6 WritePixelFastToDI()	
		Case 7 WritePixelFastToMI()	
		Case 8 DrawBlockDynamicImagetoBackBuffer()	
		Case 9 DrawBlockManagedImagetoBackBuffer()	
		Case 10 DrawBlockModDynamicImagetoBackBuffer()	
		Case 11 DrawBlockModManagedImagetoBackBuffer()	
		Case 12 CopyRectDynamicImagetoBackBuffer()	
		Case 13 CopyRectManagedImagetoBackBuffer()	
		Case 14 CopyRectModDynamicImagetoBackBuffer()	
		Case 15 CopyRectModManagedImagetoBackBuffer()	
		Case 16 CopyRectDynamicImagetoDI()
		Case 17 CopyRectManagedImagetoMI()
		Case 18 CopyRectDItoMI()
		Case 19 CopyRectMItoDI()
		Case 20 CopyModRectDItoMI()
		Case 21 CopyModRectMItoDI()
		Case 22 GrabDIFromBB()
		Case 23 GrabMIFromBB()
		Case 24 GrabDIFromDI()
		Case 25 GrabMIFromMI()
		Case 26 GrabDIFromMI()
		Case 27 GrabMIFromDI()

	End Select
	endt = MilliSecs()-st
	Flip
	Color 255,255,0
	Local lx= 450
	Text lx,ly,endt+"ms"
	Text lx+70,ly,"= "+endt/(multiplier*1.0) + " each"
	ly=ly+gap+2
	Flip	
	
	WriteLine(Results, ccPadRight(name$ + " x "+multiplier, 52) + ccPadRight(endt+"ms", 9) + "= "+endt/(multiplier*1.0) + " each")
End Function

Function EmptyForLoop()
	For n = 0 To multiplier-1
		For y = 0 To ScreenHeight-1
			For x = 0 To ScreenWidth-1
			Next
		Next
	Next	
End Function

Function ReadPixelFastFromBackBuffer()
	LockBuffer BackBuffer()
	For n = 0 To multiplier-1
		For y = 0 To ScreenHeight-1
			For x = 0 To ScreenWidth-1
				z = ReadPixelFast(x,y)
			Next
		Next
	Next	
	UnlockBuffer BackBuffer()
End Function

Function ReadPixelFastFromDI()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 2)

	SetBuffer ImageBuffer(Temp)
	LockBuffer ImageBuffer(Temp)
	For n = 0 To multiplier-1
		For y = 0 To ScreenHeight-1
			For x = 0 To ScreenWidth-1
				z = ReadPixelFast(x,y)
			Next
		Next
	Next	
	UnlockBuffer ImageBuffer(Temp)
	FreeImage Temp
	SetBuffer BackBuffer()
End Function

Function ReadPixelFastFromMI()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 1)	

	SetBuffer ImageBuffer(Temp)
	LockBuffer ImageBuffer(Temp)
	For n = 0 To multiplier-1
		For y = 0 To ScreenHeight-1
			For x = 0 To ScreenWidth-1
				z = ReadPixelFast(x,y)
			Next
		Next
	Next	
	UnlockBuffer ImageBuffer(Temp)
	FreeImage Temp
	SetBuffer BackBuffer()
End Function

Function WritePixelFastToBackBuffer()	
	LockBuffer BackBuffer()
	For n = 0 To multiplier-1
		For y = 0 To ScreenHeight-1
			For x = 0 To ScreenWidth-1
				WritePixelFast(x,y, 0)
			Next
		Next
	Next	
	UnlockBuffer BackBuffer()	
End Function

Function WritePixelFastToDI()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 2)

	SetBuffer ImageBuffer(Temp)
	LockBuffer ImageBuffer(Temp)
	For n = 0 To multiplier-1
		For y = 0 To ScreenHeight-1
			For x = 0 To ScreenWidth-1
				WritePixelFast(x,y, 0)
			Next
		Next
	Next	
	UnlockBuffer ImageBuffer(Temp)
	FreeImage Temp
	SetBuffer BackBuffer()
End Function

Function WritePixelFastToMI()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 1)

	SetBuffer ImageBuffer(Temp)
	LockBuffer ImageBuffer(Temp)
	For n = 0 To multiplier-1
		For y = 0 To ScreenHeight-1
			For x = 0 To ScreenWidth-1
				WritePixelFast(x,y, 0)
			Next
		Next
	Next	
	UnlockBuffer ImageBuffer(Temp)
	FreeImage Temp
	SetBuffer BackBuffer()
End Function

Function DrawBlockDynamicImagetoBackBuffer()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 2)	
	For n = 0 To multiplier-1				
		DrawBlock(Temp,0,0)		
	Next
	FreeImage Temp	
End Function

Function DrawBlockManagedImagetoBackBuffer()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 1)	
	For n = 0 To multiplier-1		
		DrawBlock(Temp,0,0)		
	Next
	FreeImage Temp
End Function

Function DrawBlockModDynamicImagetoBackBuffer()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 2)	
	For n = 0 To multiplier-1		
		SetBuffer ImageBuffer(Temp)
		Plot 0,0
		SetBuffer BackBuffer()
		DrawBlock(Temp,0,0)		
	Next
	FreeImage Temp	
End Function

Function DrawBlockModManagedImagetoBackBuffer()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 1)	
	For n = 0 To multiplier-1
		SetBuffer ImageBuffer(Temp)
		Plot 0,0
		SetBuffer BackBuffer()
		DrawBlock(Temp,0,0)		
	Next
	FreeImage Temp
End Function

Function CopyRectDynamicImagetoBackBuffer()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 2)
	Local ib = ImageBuffer(temp) 
	For n = 0 To multiplier-1				
		CopyRect(0,0,ScreenWidth, ScreenHeight, 0,0, ib)
	Next
	FreeImage Temp	
End Function

Function CopyRectManagedImagetoBackBuffer()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 1)
	Local ib = ImageBuffer(temp) 
	For n = 0 To multiplier-1		
		CopyRect(0,0,ScreenWidth, ScreenHeight, 0,0, ib)
	Next
	FreeImage Temp
End Function

Function CopyRectModDynamicImagetoBackBuffer()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 2)
	Local ib = ImageBuffer(temp) 
	For n = 0 To multiplier-1		
		SetBuffer ImageBuffer(Temp)
		Plot 0,0
		SetBuffer BackBuffer()
		CopyRect(0,0,ScreenWidth, ScreenHeight, 0,0, ib)
	Next
	FreeImage Temp	
End Function

Function CopyRectModManagedImagetoBackBuffer()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 1)
	Local ib = ImageBuffer(temp) 
	For n = 0 To multiplier-1
		SetBuffer ImageBuffer(Temp)
		Plot 0,0
		SetBuffer BackBuffer()
		CopyRect(0,0,ScreenWidth, ScreenHeight, 0,0, ib)
	Next
	FreeImage Temp
End Function

Function CopyRectDynamicImagetoDI()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 2)
	Temp2 = CreateImage(ScreenWidth, ScreenHeight, 1, 2)
	Local ib = ImageBuffer(temp) 
	Local ib2 = ImageBuffer(temp2) 	
	For n = 0 To multiplier-1
		CopyRect(0,0,ScreenWidth, ScreenHeight, 0,0, ib, ib2)
	Next
	FreeImage Temp
	FreeImage Temp2
End Function

Function CopyRectManagedImagetoMI()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 1)
	Temp2 = CreateImage(ScreenWidth, ScreenHeight, 1, 1)
	Local ib = ImageBuffer(temp) 
	Local ib2 = ImageBuffer(temp2) 	
	For n = 0 To multiplier-1
		CopyRect(0,0,ScreenWidth, ScreenHeight, 0,0, ib, ib2)
	Next
	FreeImage Temp
	FreeImage Temp2
End Function

Function CopyRectDItoMI()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 2)
	Temp2 = CreateImage(ScreenWidth, ScreenHeight, 1, 1)
	Local ib = ImageBuffer(temp) 
	Local ib2 = ImageBuffer(temp2) 	
	For n = 0 To multiplier-1	
		CopyRect(0,0,ScreenWidth, ScreenHeight, 0,0, ib, ib2)
	Next
	FreeImage Temp
	FreeImage Temp2
End Function

Function CopyRectMItoDI()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 1)
	Temp2 = CreateImage(ScreenWidth, ScreenHeight, 1, 2)
	Local ib = ImageBuffer(temp) 
	Local ib2 = ImageBuffer(temp2) 	
	For n = 0 To multiplier-1
		CopyRect(0,0,ScreenWidth, ScreenHeight, 0,0, ib, ib2)
	Next
	FreeImage Temp
	FreeImage Temp2
End Function

Function CopyModRectDItoMI()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 2)
	Temp2 = CreateImage(ScreenWidth, ScreenHeight, 1, 1)
	Local ib = ImageBuffer(temp) 
	Local ib2 = ImageBuffer(temp2) 	
	For n = 0 To multiplier-1
		SetBuffer ImageBuffer(Temp)
		Plot 0,0
		SetBuffer BackBuffer()
		CopyRect(0,0,ScreenWidth, ScreenHeight, 0,0, ib, ib2)
	Next
	FreeImage Temp
	FreeImage Temp2
End Function

Function CopyModRectMItoDI()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 1)
	Temp2 = CreateImage(ScreenWidth, ScreenHeight, 1, 2)
	Local ib = ImageBuffer(temp) 
	Local ib2 = ImageBuffer(temp2) 	
	For n = 0 To multiplier-1
		SetBuffer ImageBuffer(Temp)
		Plot 0,0
		SetBuffer BackBuffer()
		CopyRect(0,0,ScreenWidth, ScreenHeight, 0,0, ib, ib2)
	Next
	FreeImage Temp
	FreeImage Temp2
End Function

Function GrabDIFromBB()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 2)		
	For n = 0 To multiplier-1
		GrabImage (temp,0,0)		
	Next
	FreeImage Temp	
End Function

Function GrabMIFromBB()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 1)		
	For n = 0 To multiplier-1
		GrabImage (temp,0,0)		
	Next
	FreeImage Temp	
End Function

Function GrabDIFromDI()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 2)		
	Temp2 = CreateImage(ScreenWidth, ScreenHeight, 1, 2)		
	SetBuffer ImageBuffer(Temp2)
	For n = 0 To multiplier-1		
		GrabImage (temp,0,0)		
	Next
	SetBuffer BackBuffer()
	FreeImage Temp	
	FreeImage Temp2
End Function

Function GrabMIFromMI()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 1)		
	Temp2 = CreateImage(ScreenWidth, ScreenHeight, 1, 1)		
	SetBuffer ImageBuffer(Temp2)
	For n = 0 To multiplier-1
		GrabImage (temp,0,0)		
	Next
	SetBuffer BackBuffer()
	FreeImage Temp	
	FreeImage Temp2
End Function

Function GrabDIFromMI()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 2)		
	Temp2 = CreateImage(ScreenWidth, ScreenHeight, 1, 1)		
	SetBuffer ImageBuffer(Temp2)
	For n = 0 To multiplier-1
		GrabImage (temp,0,0)		
	Next
	SetBuffer BackBuffer()
	FreeImage Temp	
	FreeImage Temp2
End Function

Function GrabMIFromDI()
	Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 1)		
	Temp2 = CreateImage(ScreenWidth, ScreenHeight, 1, 2)		
	SetBuffer ImageBuffer(Temp2)
	For n = 0 To multiplier-1
		GrabImage (temp,0,0)		
	Next
	SetBuffer BackBuffer()
	FreeImage Temp	
	FreeImage Temp2
End Function

Function ccPadRight$(TheString$, TheSize)
	sl = TheSize - Len(TheString$) ; Get length of string
	If sl > 0 Then ; Needs padding?
		For p = 1 To sl										
			z$ = z$ + " " ; make a blank string
		Next
		TheString$ = TheString$ + z$; add the blank string to the main string
	EndIf
	Return TheString$
End Function 


The stats are pretty damn important for developers. If there's wasn't a delay in sending modified managed images to the backbuffer I'd continue my game in BPlus but I can't get the effects in and maintain speed so it's gonna be in BMax now.

Max doesn't have imagebuffers. It has images (like dynamic images) and pixmaps (like scratch images). You can only draw to the backbuffer. Pixmaps can only be drawn to via read/writepixel, or direct buffer manipulation.

Any modifications made to an image in this way involves grabbing the image from vidmem into a pixmap (slow) and then reupping it back to vidmem (slow). And the delays seem to be a lot more harsh compared to B+'s managed images.

He's using Max because of the 3d accelrated effects, not because of buffer access.

yeah I won't need to use buffer's anymore (I hope)

"sswift: I tested scratch and it was the same as managed image so I left it off. How can managed be in VRAM and RAM at the same time unless there's a copy in each."

That's exactly how it is set up. When you write to a managed image, I think Blitz only writes to the copy in memory, and sets a flag for the image in video ram indicating it is out of date. Then Blitz copies the image to video ram at some point.

Since you indicate that you are doing a lot of writepixels, and that was fairly fast, and the managed image had that 45ms delay, that indicates to me that the copy occurs the minute you try to paste the modified managed image into an image stored only in vram. I would wager that pasting a modified managed image into another managed image would simply ocpy to the other image's ram copy, and set its flag, so that would be fast. I haven't checked the numbers to see if that is the case, but I'm pretty sure it is.

"Managed images are very fast for doing ReadPixelFast on for visual effects, whereas dynamic ones are not. All the 45Ms cases are "Changed" Managed images i.e. the change is made in RAM and copied to VRAM and this is the delay."

Yeah, I thought maybe the managed images were updating after you got done with the writepixels or something and before the loop, but that is probably not the case as Blitz has no idea when you're done with it. So it gets written when you actually try to paste it onto the video card.


"That's my theory anyway. It meant that a triple buffer system so the effects can be applied in the 3rd buffer (RAM copy) is actually too slow due to the copy time when it moves over to VRAM. If my theory is wrong then I'll eat my digitial hat, no actually, I'd like to hear from someone that REALLY knows."


You'd better get some salt then, because my BOB system demo, (check out the links below) supports triple buffering, and if you use an effect like any of the blending modes which require a lot of readpixels, then you'll find that triplebuffering dramatically improves speed.

Triple buffering however would not improve speed if you were not using lots of readpixels. And triplebuffering comes at a huge cost. Triple buffering an 800x600 scene will cut the framerate to 70fps just for enabling the triple buffering. But since blitting to the image in ram is so fast, the cost after that point is realtively small, so it is still worthwhile to do if you want to do a lot of reaspixels and you don't mind if your game runs at 60fps rather than 400fps.

Now, if you are using max because you want effects like that, then the only thing you need to ask yourself is what the minimum spec system you want to run on is, and who your game is aimed at. Max would be much faster for blending effects because it's 3d acceletated. But it might be slower than doing it manually on a system without a 3d accelerator card. Those would be pretty old systems I'd imagine, but I think my aunt has a PC that's new enough to run XP but doesn't have a 3d accelerator, so there might be a lot of them out there still.

I actually tested modified DI to DI and MI to MI and both were very fast, it's only modified MI to DI (or Backbuffer) that's a bit slower (excluding the really slow DI/Backbuffer to MI).

Now my point about the triple buffer is this: You make a 800x600 managed image (in RAM) (this is the 3rd buffer) and you draw to this, and any effects read from this and write back to it thus are very fast. Then just before flip, you Drawblock the managed image to the BackBuffer BUT this takes a minimum of 4ms even on the fastest systems here. Some of those systems take over 20ms! And that's only drawing one pixel, no effects, no game logic, no other drawing. This would mean an FPS of 30 (i.e. half 60) or less on slower systems, assuming VSync is enabled.

Tim pointed out your bob system, but I'd already seen the demo, sure it's fast on my P4 but what about slower systems? Also you aren't Vsyncing (hense > 100FPS). How do you do your triple buffer system, different from mine?

Take dirty rects, say you only update portions of the backbuffer where Buffer3 has changed, it STILL takes 4ms due to some kind of inherent "firing up the comms to the VRAM" delay, don't ask me what causes the delay but it's there!

Another possibility (bearing in mind that WritePixel fast on an 800x600 screen is about twice as slow as a draw block) is to implement a dirty rects system that never actually copies from the managed Buffer3 using copyrect or drawblock but uses readpixelfast on Buffer3 and writepixelfast on the BackBuffer. Providing you are updating less than half the screen, this could be faster. However, the 4ms delay may still exist as you are still reading from a managed image, although you aren't needing to use SetBuffer Buffer3, you still have to use LockBuffer ImageBuffer(Buffer3). Maybe I'll do a test. The only other other poss. is to make a bank which is your image (Buffer3) and use custom drawing routines to it and write those integers directly to the backbuffer without using any LockBuffers or ReadPixelFast on Buffer3, get it?

OK, I did the test mentioned in the last post i.e. using writepixel fast instead of copyrect (or drawblock) and wooooo it is faster!

Try running this in BPlus and changing the UseCopyRect variable from 0 to 1. WritePixel fast gives me 0.11ms and CopyRect gives me 3.13ms.

Global ScreenWidth = 800
Global ScreenHeight = 600
Global BitDepth = 32
Global multiplier = 100

Graphics (ScreenWidth, ScreenHeight, BitDepth, 0)

Global Temp = CreateImage(ScreenWidth, ScreenHeight, 1, 1)

Text 0,0,"press any key"
Flip
WaitKey

Local UseCopyRect=0

Flip
st = MilliSecs()
For n = 1 To multiplier
	LockBuffer ImageBuffer(Temp)
	b = LockedPixels(ImageBuffer(Temp))
	PokeInt(b,0,$ff00ff)
	If UseCopyRect Then
		CopyRect(0,0,1,1,100,100,ImageBuffer(Temp))
	Else
		LockBuffer BackBuffer()
		WritePixelFast(100,100,ReadPixelFast(0,0,ImageBuffer(Temp)))		
		UnlockBuffer BackBuffer()
	EndIf
	UnlockBuffer ImageBuffer(Temp)
Next
endt = MilliSecs() - st
Flip
Flip
Text 0,20,"x "+multiplier+ " = " + endt+"ms" + " = " + endt/(multiplier*1.0) + "ms each"
Text 0,40,"press any key"
Flip
FreeImage Temp
WaitKey


So to conclude a triple buffer system using dirty rects which are drawn with writepixel fast instead of copyRect will be the fastest method providing you are redrawing less than half the screen. Really a "real world" application needs to be made to test this on different spec PCs.

[edit] hmm rethink ... In my benchmark I was simply WritePixelFasting a 0 I wasn't doing a ReadPixelFast to get the source colour, this would slow it down by half so the dirty rects would only be faster given that 1.4 of the screen or less needed updating. But still, this allows for lots of puzzle games with hardly any screen updates that want a triple buffer for effects. Problems will only arise if many objects need to move at once.

wooooo swifty swifty! You have inadvertently hit the nail on the head. You got me thinking about scratch images which are held in RAM *ONLY*. I said they were the same speed as managed images, yes true, scratch to scratch and scratch to backbuffer is same if using managed images instead BUT there is one VITAL difference. Remember I said that if you modify a single pixel on a big managed image and you try to copy that single pixel to the backbuffer you get this peak where it takes a bit too long, and we figured this is because a copy of the whole managed image is being made in VRAM ... well if you use a scratch image instead, NO COPY is made in VRAM so you can transfer a single pixel in around 0ms! There IS NO STUPID DELAY! This means I can make my triple buffer system using a scratch image and rather than sending the whole massive image to the backbuffer (which is just as slow as for managed images), I can send only the areas that need updating and it will be loads faster! Thus Dirty Rects come back into their own again!

Only problem is that as you aren't redrawing the entire backbuffer each time you effectively need to keep two sets of dirty rects, one for the Front buffer and one for the backbuffer as it's no good calling flip and using the dirty rect locations for the previous buffer to redraw the background on the current buffer as the objects aren't in the same place! I hope that makes sense. But that is a minor problem of just having two lists of Dirty rects and appying the correct one to the correct backbuffer.