Performance problems vs. DirectX

I’ve just finished porting a simple test app from DirectX over to SDL. I love
SDL, but I can’t seem to get decent performance out of it. My test app opens an
800x600 window, and calls FillRect every frame. It also displays an FPS counter
using a simple sprite font.

This test app runs on DirectX at around 250 fps on my average PC. The SDL
version runs at 80fps. I know very little about DirectX, so rest assured that
that version is very simple-minded and basic.

I’ve played endlessly with the surface formats, pixel formats, and blitting
options in SDL. I’ve scoured the forums, FAQs, and docs, but I can’t explain
this poor performance.

Any suggestions would be greatly appreciated!

-blondie

Sounds like it could be the difference between h/w accelerated and s/w
rendering…

Are you asking for an SDL_HWSURFACE display surface? (If you don’t,
SDL will manage the display surface, and DirectX won’t be able to
accelerate anything, except possibly the shadow->VRAM blit in
SDL_Flip().)

Running in windowed mode could cause trouble as well…

Can you provide a minimal code example? (I think we can forget about
the on-screen fps counter, assuming it just covers a tiny fraction of
the display surface. :slight_smile:

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Monday 12 April 2004 05.19, blondie wrote:

I’ve just finished porting a simple test app from DirectX over to
SDL. I love SDL, but I can’t seem to get decent performance out of
it. My test app opens an 800x600 window, and calls FillRect every
frame. It also displays an FPS counter using a simple sprite font.

This test app runs on DirectX at around 250 fps on my average PC.
The SDL version runs at 80fps.

blondie wrote:

I’ve played endlessly with the surface formats, pixel formats, and blitting
options in SDL. I’ve scoured the forums, FAQs, and docs, but I can’t explain
this poor performance.
Any suggestions would be greatly appreciated!

If you don’t post the code there is not much we can do to help you…

Anyway check those:

  • Use SDL_HWSURFACE|SDL_DOUBLEBUF in the SetVideoMode call and
    SDL_Flip() to update the video surface.

  • Check if your FPS is the same as your monitor vertical refresh, maybe
    you have the vblank sync enabled by default (and you disable it in the
    DirectX app).

Bye,
Gabry

[…]

  • Check if your FPS is the same as your monitor vertical refresh,
    maybe you have the vblank sync enabled by default (and you disable
    it in the DirectX app).

Yes, of course! Didn’t notice the “magic” 80 fps value, which sounds
very much like a sensible refresh rate for 800x600.

Try removing the SDL_DOUBLEBUF flag, and/or run the app in windowed
mode. One or both will eliminate retrace sync on most targets.

Now, note that this is just for testing. Retrace sync is a Very Good
Thing. It allows you to get the smoothest animation without wasting
CPU and/or GPU power.

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Tuesday 20 April 2004 16.04, Gabriele Greco wrote:

a friend of mine is actualy moving to directx from sdl (i had him move from
directx to sdl about a year ago) because w/ directx it was alot faster he
says.

no idea whats wrong w/ his code so no idea how to fix but i emailed him your
tips and he said he tried your first tip:

  • Use SDL_HWSURFACE|SDL_DOUBLEBUF in the SetVideoMode call and
    SDL_Flip() to update the video surface.

and it made it like 10 times slower.

any suggestions there? does that point out anything obvious?

thanks,
Alan> ----- Original Message -----

From: gabriele.greco@darts.it (Gabriele Greco)
To:
Sent: Tuesday, April 20, 2004 7:04 AM
Subject: Re: [SDL] Performance problems vs. DirectX

blondie wrote:

I’ve played endlessly with the surface formats, pixel formats, and
blitting

options in SDL. I’ve scoured the forums, FAQs, and docs, but I can’t
explain

this poor performance.
Any suggestions would be greatly appreciated!

If you don’t post the code there is not much we can do to help you…

Anyway check those:

  • Use SDL_HWSURFACE|SDL_DOUBLEBUF in the SetVideoMode call and
    SDL_Flip() to update the video surface.

  • Check if your FPS is the same as your monitor vertical refresh, maybe
    you have the vblank sync enabled by default (and you disable it in the
    DirectX app).

Bye,
Gabry


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

Could be that it’s all s/w rendering into VRAM if you do only that.
You should also make sure all source surfaces are in the rigth
format, and in VRAM, if the driver likes that best. (Check this at
run time! If you don’t have h/w acceleration for the blits you’re
going to do, putting the source surfaces in VRAM is the worst thing
you can do.)

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Tuesday 20 April 2004 20.52, Alan Wolfe wrote:

a friend of mine is actualy moving to directx from sdl (i had him
move from directx to sdl about a year ago) because w/ directx it
was alot faster he says.

no idea whats wrong w/ his code so no idea how to fix but i emailed
him your tips and he said he tried your first tip:

  • Use SDL_HWSURFACE|SDL_DOUBLEBUF in the SetVideoMode call and
    SDL_Flip() to update the video surface.

and it made it like 10 times slower.

any suggestions there? does that point out anything obvious?

Isn’t there also a flag you need to set to get things like hardware
accelerated blits and such? SDL_HWACCEL or something?

Also, make sure you do SDL_DisplayFormat() (or SDL_DisplayFormatAlpha() for
alpha transparency) on whatever surfaces you’re blitting. If you try to blit
a surface to the screen that isn’t in the same format as the screen surface,
SDL will automatically convert the surface to the right format for you. The
problem is, this has to be done every frame, since SDL doesn’t keep the
converted version of the surface; each and every time you blit that surface,
SDL has to redo the conversion. So, what you can do is call
SDL_DisplayFormat() (or SDL_DisplayFormatAlpha() ) on a surface when you
first load it, which will convert it to the screen surface’s format and
return a pointer to the converted surface. Then you blit the properly
formatted surface.

And if you’re using surfaces with alpha transparency, there can be a decent
performance increase from turning on a surface’s RLEACCEL flag:
… create and load an SDL surface …
SDL_SetAlpha(surface,SDL_RLEACCEL|SDL_SRCALPHA,255);
Just be sure to read the caveats to SDL’s alpha transparency on the
SDL_SetAlpha() page in the SDL docs (http://sdldoc.csn.ul.ie/sdlsetalpha.php)

As to the SDL_Flip() thing, to me it seems that SDL never does true page
flipping; rather, it just copies the back buffer to the front buffer. At
least, this is how it seems on some hardware. It would therefor make sense
that doing SDL_UpdateRects() would be faster, since you would only be
blitting part of the back buffer to the front buffer instead of the whole
thing.

Try using SDL_SWSURFACE|SDL_DOUBLEBUF instead, and see if that’s faster. If
your hardware (or the drivers) don’t support 2D blitting in hardware, then
storing the surfaces in VRAM will actually be slower than storing them in
main memory (since the CPU will have to do the blitting, and the CPU can
access main memory faster than it can access video memory).

-Sean RidenourOn Tuesday 20 April 2004 02:25 pm, David Olofson wrote:

On Tuesday 20 April 2004 20.52, Alan Wolfe wrote:

a friend of mine is actualy moving to directx from sdl (i had him
move from directx to sdl about a year ago) because w/ directx it
was alot faster he says.

no idea whats wrong w/ his code so no idea how to fix but i emailed
him your tips and he said he tried your first tip:

  • Use SDL_HWSURFACE|SDL_DOUBLEBUF in the SetVideoMode call and
    SDL_Flip() to update the video surface.

and it made it like 10 times slower.

any suggestions there? does that point out anything obvious?

Could be that it’s all s/w rendering into VRAM if you do only that.
You should also make sure all source surfaces are in the rigth
format, and in VRAM, if the driver likes that best. (Check this at
run time! If you don’t have h/w acceleration for the blits you’re
going to do, putting the source surfaces in VRAM is the worst thing
you can do.)

[…]

Isn’t there also a flag you need to set to get things like hardware
accelerated blits and such? SDL_HWACCEL or something?

No, unless I’m mistaken, you simply get h/w acceleration whenever the
circumtances are right; ie when the backend and driver supports
accelerated blits from your source surfaceformat and memory type
(VRAM or system memory) to your destination format and memory type.
Anything else falls back to s/w rendering.

As to the SDL_Flip() thing, to me it seems that SDL never does true
page flipping; rather, it just copies the back buffer to the front
buffer. At least, this is how it seems on some hardware.

It certainly seems to do true page flipping on DirectX/Win32 on all
h/w I’ve tried it on so far…

If you’re on Linux, you don’t have many targets and drivers that can
do h/w page flipping at all, though.

Also note that very few video subsystems support h/w page flipping in
windowed mode.

It would
therefor make sense that doing SDL_UpdateRects() would be faster,
since you would only be blitting part of the back buffer to the
front buffer instead of the whole thing.

…unless you’re scrolling the whole screen. :wink:

Try using SDL_SWSURFACE|SDL_DOUBLEBUF instead, and see if that’s
faster.

In SDL_video.h:

#define SDL_SWSURFACE 0x00000000 <==
#define SDL_HWSURFACE 0x00000001

#define SDL_DOUBLEBUF 0x40000000

Somewhere in SDL_video.c:

    if ( (flags&SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
            /* Use hardware surfaces when double-buffering */
            flags |= SDL_HWSURFACE;
    }

So, that should be equivalent to SDL_HWSURFACE|SDL_DOUBLEBUF, or just
plain SDL_DOUBLEBUF. What you get is a double buffered h/w surface,
provided the API and driver support it.

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Thursday 22 April 2004 05.05, Sean Ridenour wrote: