Sdl Performance Issues


ekureuil

Still Fresh
Joined
Aug 8, 2009
Messages
12
Hello,

On this rainy sunday, I took some time to test drawing circles with SDL gfx lib. And I find that performances are not so ok. I can draw around 4000 circles in 22 seconds ... This makes 3 circles at 60 fps ... I need more than that :-(

My pc (which is *not* powerful) runs twice quicker than that (it's a tx 1000 tablet pc, AMD Turion X2, a dual core, with each core at 800 Mhz). So overall, the wiz is doing well. This must be my program that's slow ... But I would like to ask you guys if you believe I can achieve better performances ... i use software drawing, so may be do I already get the maximal performances ???

I am drawing with filledCircleRGBA, with each parameter random with 200 as the maximum value for radius. Each is directly draw on screen surface, which is then flipped ...

... Also, I tested the SDL replacement not to have that awful tearing ... and I get around 1000 circles in 22 seconds ... lol ... :)

If you want to see the code, go here.


eKuReUiL
 
Alpha blending is slow, you should only use it in small doses for effect.

If it's still too slow even without alpha blending, try implementing a circle-drawing algorithm yourself with the 16bit 320px-wide screen in mind (SDL_gfx does all kinds of unnecessary checks each time it draws something). If that is too slow still, why not make look-up tables for all the circle sizes you need :)
 
Aren't you really benchmarking the time it takes to poll for events, draw the circle, draw a 320x30 filled rectangle, do a bunch of TTF renderings, blit a bunch of text glyphs, flip the screen (which involves a full on 320x240 blit because it's an SWSURFACE), and a bunch of other little things like calls to rand() and modulos? I think of all those things drawing the circle would take nearly the least time. For something that's much closer to what you want to find out you should time how long it takes to draw many circles, say 1000, then do all that other stuff/print the results.

By the way, that SDL version w/o tearing is most likely waiting for vsync when you do SDL_Flip. So you're already limiting yourself to one circle per frame at most, hence why your results there are even slower. I believe GP2X defaults to something inbetween 50 and 60Hz so there you have it. Okay, I can see you posted this in the Wiz section even though the code references GP2X, but the default for SOME firmwares on Wiz is similar.

Okay, now about the circles themselves. I don't know the inner workings of filledCircleRGBA, but unless you want to draw a bunch of very small circles you're going to be limited by linefills, not the edge conversion of the circles, which can be done really quickly using Bresenham's circle algorithm (LUT would not be needed here). For this to perform at its best, SDL is going to have to have an optimized 32bit color -> 16bit fill rect (or fill line?) implementation that performs blending. The right way to do this is to convert the 32bit color into a 16bit one and multiply its components by the alpha before entering the fill, then for each pixel multiply the components by (1 - alpha) and add/repack the two. If this is done intelligently it shouldn't be that slow computation-wise, what's going to get you are the cacheline loads.

See, the thing is, a 320x240x16bpp framebuffer takes 320 * 240 * 2 bytes, or 150KB. That's way more than the 16KB of data cache the GP2X/Wiz ARM9 has, and you end up loading a cache line every time, unless your circle overlaps the last 16KB of the last one. For reference, 16KB / 320 / 2 = 25.6 lines. That's what you can store in the cache.

If you don't have alpha blending then it's entirely possible to draw circles limited to bus speed. Thanks to the writebuffer on the ARM9, you'll be able to compute the next pixel while you're drawing the current, but even that takes almost no time when you aren't blending. The bus speed on GP2X is 100MHz @ 32bits Wiz is 133MHz * 16bits * 2, so 400MB/sec and 533MB/sec. You need two bytes per pixel, so you can draw 200MPixel/s or 266MPixel/sec. Naturally you need some time for other things. Since you're not drawing straight to the framebuffer you'll need a lot of time to blit the screen because you have to do a cache load and write for each cache line's worth of pixels. So in that way it's much better to get HW surfaces and write straight to the framebuffer, using double buffering to flip. I don't know if SDL on GP2X/Wiz supports this. I do it using straight hardware manipulation.

So, if you draw opaque circles you can go at bus speed and if you draw transparent ones.. well, it's much worse, because cacheline loads aren't fast on either platform, especially Wiz. So it's worse than even half speed. But there's actually a way around this.

Let's say that you can schedule to draw N circles ahead of time, possibly drawing other stuff inbetween. If you do this then you can batch the draw operations of all of these things per scanline or per groups of scanlines (let's say 8, maybe 16 of them). What that means is that the read-modify-write cycles take place inside the cache, then get written back via the write buffer with no reads, preferably straight to the framebuffer. Now not only are your alpha blits much faster (especially if they're very well optimized) but you also don't have to write to the write buffer multiple times for pixels that overlap each other. So your worst case performance on bus usage is bounded, with the in-CPU usage being what grows. There is, however, a fixed penalty of having to copy those lines to the framebuffer, but if you're doing alpha stuff or have a ton of overdraw then it's definitely worth it.
 
There's an SDL with vsync forced on and no tearing?
That's just what I need!
I'm doing a software delay to hit around 60 fps anyway...
Can anyone link me up to that? :)
 
Thanks for the complete answer ...


Aren't you really benchmarking the time it takes to poll for events, draw the circle, draw a 320x30 filled rectangle, do a bunch of TTF renderings, blit a bunch of text glyphs, flip the screen (which involves a full on 320x240 blit because it's an SWSURFACE), and a bunch of other little things like calls to rand() and modulos? I think of all those things drawing the circle would take nearly the least time. For something that's much closer to what you want to find out you should time how long it takes to draw many circles, say 1000, then do all that other stuff/print the results.

I know that ! I don't care about the maximum speed value, I care about my current game implementation that too slow because of "simple" alpha circles. I can have here a *very rough* estimation of how my game will handle.


I think that all of those optimisations are beyond my time investment quota. I will read them more carefully when I really have time.

I thought about using opengl es (at the last resort) ... but I saw circle aren't implemented. Is it still possible to do something like bresenham drawing effenciently ?? (and with alpha ?)

And i care about portability ... is openglES good in that respect ?

As for the sdl version without tearing, it is here:
http://dl.openhandhelds.org/cgi-bin/wiz.cgi?0,0,0,0,23,138

I had to use export LD_LIBRARY_PATH=.:/lib so that lib can be put next to the program.


eKuReUiL
 
eKuReUiL said:
I know that ! I don't care about the maximum speed value, I care about my current game implementation that too slow because of "simple" alpha circles. I can have here a *very rough* estimation of how my game will handle.

This is not even a very rough estimation. You need to change the way you're doing this if you care about determining how much performance circles take. Your benchmark is completely useless. I don't know why you're fighting this, making it correct is not a difficult change. I mean, you asked why it was so much slower than you expected and I explained it to you, but you don't look like you care.

eKuReUiL said:
I think that all of those optimisations are beyond my time investment quota. I will read them more carefully when I really have time.

I thought about using opengl es (at the last resort) ... but I saw circle aren't implemented. Is it still possible to do something like bresenham drawing effenciently ?? (and with alpha ?)

First fix your benchmark find out how many circles per frame you can actually draw. The number will be dramatically higher than what you're seeing now. My information was given to show you theoretical limits and how to improve alpha blending with software circles, ONLY IF it wasn't already fast enough. Do the proper benchmark first then determine if it's enough. You could also try telling us exactly how many circles (of what typical sizes) per frame you think you need.

If you want to draw circles in 3D then you need to use quads and Bresenham's circle algorithm (or something else) to find where to draw them. If you do one quad per line (or probably one quad per two lines) then they'll be as good as the software algorithm. If you do more than edges will be interpolated and it'll look pointy, but to some extent it'd probably be good enough.

The 3D chip, not being a deferred renderer, is going to be limited by bus bandwidth per pixel the exact same ways the ARM9 would be, so you wouldn't get significantly higher overall fillrate. Likewise, it'll have to load at bus speed for alpha blending too, and my guess is that it won't keep framebuffer cache around, not that it'd do better anyway. I don't know how this will effect its ability to read from the framebuffer. The ARM9 is very very slow when doing non-cached reads, implying a ton of latency. But the 3D core might not have this problem. If there's at least some burst reading to span multiple pixels then it'll probably be the same.

eKuReUiL said:
And i care about portability ... is openglES good in that respect ?

Like all things that depends on what you actually want portability to - if you want it to run on desktops then you'll have to use a wrapper and a lot of handhelds won't have it.
 
Last edited by a moderator:
My game is not about *only* circle drawing (and I know you know that). What my game do is more cpu demanding than some rand (which I use in my real prog) and some modulo and some blitting ... so why would a circle bench alone would be better that this one ?

In fact I already did that : no ttf, and print every 1000, and it was better (how would it be otherwise ?), not drastically better though, but in the end I found it not easy to handle on wiz ... A benchmark is relative to what you want to know ..


To make it clear: I don't think I said what I wanted to test ... just that this test was slow (from my *untold* point of view) and I suspected that maybe I did something wrong regarding sdl surface handling ... so I asked for you guys if I couldn't improve this particular benchmark on that sdl perpective...

My game (and everything is still at research level of what can be done ...) want to draw circles, something like 10 at maximum depending on the stylus position, alpha is mandatory to see something :). So I thought that with a random drawing test I would not be too far from what the user can do.

This test confirmed that : either this test is still faulty in term of surface handling, like my original app,
either this circle drawing is too slow, either my requirements must be lowered down.
I think that this is not a completely useless test because: my app run at something like 10 fps when there is 10 circles, and if you look at my results, you see that it mostly agree with that.

Oh and english isn't my mother tongue as you may have noticed, and if I am not clear, please, at least forgive me on that level.
 
Back
Top