GP2X Faster 32-bpp To 16-bpp Blit


HenrikE

Still Fresh
Joined
Jun 18, 2007
Messages
42
Was inspired by SenorQuack's replacement for fb_write in SDL (converting 32-bit color to a GP2X 16-bit framebuffer), so I made my own.

FastBlitV1 and FastBlitV2 were my two optimizations, both went from 12 to 8 instructions per pixel, and both require alpha channel (typ 8 bits in the pixel word) to be 0. Normally not a problem, since this is for letting SDL render sprites, mix, overlay, etc in 32 bit mode to a final 32-bpp buffer. So unless those bits are used as (garbage?) storage in your game or engine :ph34r: you only have to strip them when you load pictures, if at all.

The top one on the page, Version 1, does 8 pixels at a time, Version 2 further down does 16.


FastBlitV2 takes 74.1% of A_SN's original fb_write, or 22.2% faster than Senor Quack's fb_write. It's a plug-in replacement for both.


Download link
 
Hehe, just after I posted this A_SN sent me his version. After I optimized it and plopped it into my benchmark code, it was 1.9% faster! For some reason I get black pixels out, but that's probably some 'late in the night' issue.

If you have 4MB free RAM for the table he uses, use it! My tableless version can only be optimized further by using RLE, which costs instructions... And if you use "game graphics" with a total onscreen color-count of less than 2048(1024?), it will have some table lookups in the cache, and so gain some more speed! Or if you have true truecolor gfx, but a large % of the 32bpp pixels have the exact same RGB value, such as backgrounds with few colors, or lots of text with the same color, for example.

4MB table... never crossed my mind... well, I've (re)learned my lesson :)
 
Might have to bring bad news. The code from A_SN masked the table offset wrong, so that only two values in the entire 4MB table were used. Which meant that those were in the cache for every lookup. I made it look up correct values and corrected the code to that generated the table, and now I have a beautiful picture! :)

That's good, but the execution time quadrupled, at least.

That's the theory anyway, will test this tomorrow by simply dropping my asm in instead. If it's the same slow speed, there is an error outside fb_write. If it's just like when I benched mine, the asm is slow.
 
Test results:

I used two pictures: a picture with 10000's of colors, and a picture with hundreds of colors.

Picture - A_SN's LUT blit - FastBlitV2
S.M.War - 8363 ms - 5786 ms
Penguin - 41771 ms - 5686 ms

Yeah, that's not a typo. If you have non-pixeled graphics, like with gradients and antialiasing, A_SN's fb_write is more than 7 times slower. And if you have pixeled graphics, it's 45% slower.

Crap. I really had hopes for using A_SN's technique (also for other table lookup stuff) but now I'll think twice before using a table - at least one larger than 4KB, or where don't I know the same table addresses will be revisited often.

If someone has some trick up his sleeve to make fast table lookups, please share! But it just seems too unreliable - what most coders want I guess is a stable execution time and a guaranteed maximum execution time - no use having a fast routine if it starts stuttering when a colorful object enters the screen. Seems better to rely on bursts, line fill, and internal processing rather than messing up the cache with too many single loads.
 
I had a feeling A_SN's being faster was way too good to be true. :/

Although, the worst time would probably be a lot better if the table is in uncached memory.
 
Exophase said:
I had a feeling A_SN's being faster was way too good to be true. :/

Although, the worst time would probably be a lot better if the table is in uncached memory.
Because lookups won't cause linefills that never get used but just fill up the cache. Might look at that for other tables - but since the table technique applied in this case result in very little gain even if you have two color values onscreen ;) I don't feel like pursuing it further.

Splitting the stmia's and putting them after ldmia's (in this case) brought me to 5.301 ms/call. Will report if I spend more time on this - the links above will give you the latest release in any case...

Update: Alignment together with the split stmia rearrangement gave an average 5.142 ms/call, will try more tomorrow...
 
Last edited by a moderator:
Back
Top