Results 1 to 5 of 5

Thread: Super Slow SDL (about 1/3 frame per second...)

  1. #1

    Super Slow SDL (about 1/3 frame per second...)

    Hey - Good afternoon,

    My apologies - I'm a bit of a noob around here

    I'm still trying to learn the basics of SDL and have got an issue. All the files related to the project are on http://www.savefile.com/files/340504 - its about a 250kb.

    I'm writing an isometric engine (well the test more just shows an isometric map - learning SDLVideo at the moment). It displays the map originally almost instantly - matter of milliseconds however when I try to use the arrows to move the map, as I coded, it sucks up about 96% of my CPU and takes about 4 seconds before it updates the screen. I can't find the reason why - it doesn't seem to have any issues the first time, but the second call of the procedure makes it take absolutely ages blitting.

    Sorry - the code isn't too neat, but its readable.

    Any advice would be greatly appreciated!


    Lochok

  2. #2

    Super Slow SDL (about 1/3 frame per second...)

    Hi Lochok,

    Welcome to the site, I've had a brief look at your code. I can't run it at the moment as I'm at work. But it looks like your rendering algorithm is quite wasteful.

    If I'm reading it correctly,

    You create a seperate layer object for each layer in your map. So if you have 3 layers, each frame you're software blitting (800x600x3)x3, that's not even including any tile rendering. On top of this, you have the overhead of rendering the tiles to each layer.

    There are things you can do to speed this up.

    You are doubling up your work. You don't need to do this. Remember, anything you render using software has to travel down the AGP bus and it's got a limited bandwidth. Send as little as possible and you'll see your render speed increase.

    1, do not render to layer surfaces. Treat your layers as logical entities instead of physical entities. Blit your tiles directly to the main screen surface. Put this in a loop to render the lowest layer + any sprites, then the next lowest and so on.. this will give you exactly the same effect as your layer routine but without the massive overhead of re-blitting the entire thing via the layer surface.

    2. You're using 24bit, consider 16bit or 32. I've had performance problems with 24 bit and for some odd reason, 24bit was slower than 32 bit. 16 bit should be twice as fast as 32 bit because you're only sending half the amount of information. I'd really only use 32bit colour if I was using Hardware using OpenGL.

    3. You're doing 2 flips at the end of your loop. You really only need one.

    You're also only rendering when the player moves. Is this what you really want? This will mean that you won't be able to have any ambient animation.

    Apart from the things I've mentioned, I can't see immediately what's causing such a long delay.

    I'll run it tonight when I get home.

  3. #3

    Super Slow SDL (about 1/3 frame per second...)

    Just had another look, it looks like your problem might be down to your Event loop.

    Try moving your render code out of the main loop. If you think about it, if you hit the arrow key, it's going to send loads of events to the buffer.. these will have to be processed.. this is normally very fast, but you're doing rendering in the meantime.

    [pascal]
    while stillrunning do begin

    upPressed := false;
    leftPressed := false;
    rightPressed := false;
    downPressed := false;

    While SDL_PollEvent( @event ) > 0 do begin
    If Event.type_ = SDL_QUITEV then StillRunning := False;
    If Event.type_ = SDL_KEYUP then begin
    Case Event.key.keysym.sym of
    SDLK_Escape: StillRunning := False;
    SDLK_Up: upPressed := true;
    SDLK_Down: downPressed := true;
    SDLK_Left: leftPressed := true;
    SDLK_Right: rightPressed := true;
    end;

    Writeln('Keypress Detected ', FormatDateTime('tt', now));;

    end;
    end;


    if upPressed then OffSetY := OffsetY + 96;
    if downPressed then OffSetY := OffsetY - 96;
    if leftPressed then OffsetX := OffsetX + 128;
    if rightPressed then OffsetX := OffsetX - 128;

    DrawMapToBuf(OffsetX, OffsetY);
    Writeln('Flipping ', FormatDateTime('tt', now));
    SDL_Flip(Scr);
    Writeln('Done ', FormatDateTime('tt', now));

    end;

    [/pascal]

    I bet this gives you better results.

  4. #4

    Super Slow SDL (about 1/3 frame per second...)

    OK. I've had a tinker and found that your main problem was in the rendering code.. it was just TOO Busy.

    So I've altered it for you and now it's as fast as a fast thing.
    Also, I've changed your input code. You were only testing for Key Up. No doubt you will have tried Key down and found there to be no noticable difference.. well, SDL doesn't do Key repeats. So I've used flags. I set them on Key Down and reset them on Key Up. Works lovely

    Here's the code.

    [pascal]

    program sdltest4;


    uses
    sdl,
    sysutils;

    var scr: PSDL_Surface; // Our main screen
    Tiles, TileIn: PSDL_Surface;
    TmpLayer: PSDL_Surface;
    Layers: Array of PSDL_Surface;
    LayerCount: Word;
    TileWidth, TileHeight: Word;
    MapWidth, MapHeight: Word;
    stillrunning: Boolean;
    event: TSDL_Event;
    MapData: Array of Word;
    OffsetX, OffsetY: Integer;

    leftPressed : boolean;
    rightPressed : boolean;
    upPressed : boolean;
    downPressed : boolean;

    Procedure LoadMap(MapPath: String);
    var
    MapFile: Text;
    CountLayer, CountX, CountY: Word;
    begin
    Assign (Mapfile, Mappath);
    Reset (Mapfile);
    Read(MapFile, TileWidth);
    Read(MapFile, TileHeight);
    Read(MapFile, MapWidth);
    Read(MapFile, MapHeight);
    Read(MapFile, LayerCount);
    Setlength(Layers, LayerCount);
    For CountLayer := 0 to (LayerCount-1) do begin
    TmpLayer := SDL_CreateRGBSurface( SDL_HWSURFACE, Scr^.w, Scr^.h, Scr^.format
    .bitsperpixel,
    0,0,0,0);

    Layers[CountLayer] := SDL_DisplayFormat(TmpLayer);
    SDL_SetColorKey(Layers[CountLayer], SDL_SRCColorKey or SDL_RLEAccel,
    SDL_MapRGB(Scr.Format, 0, 0, 0));

    end;
    SetLength(MapData, MapWidth*LayerCount*MapHeight);
    For CountLayer := 0 to (LayerCount-1) do
    for CountX := 0 to (MapWidth-1) do
    for CountY := 0 to (MapHeight-1) do
    Read(MapFile, MapData[CountLayer*MapWidth*MapHeight+CountX*MapHeight+Cou ntY]);
    Close (mapFile);
    end;

    Procedure DrawMapToBuf(TopX, TopY: Word);
    var
    CountLayer, CountX, CountY: Word;
    CurX, CurY: Integer;
    SourceRect, DestRect: TSDL_Rect;
    begin
    //Writeln ('Started Drawmaptobuf ', FormatDateTime('tt', now));

    CurX := TopX;
    CurY := TopY;

    SDL_Fillrect(Scr,@DestRect,sdl_maprgb(Scr.Format, 0, 0, 0));

    //Paint to seperate layers
    For CountLayer := 0 to (LayerCount-1) do begin
    SDL_Fillrect(Layers[CountLayer],nil,sdl_maprgb(Scr.Format, 0, 0, 0));
    for CountX := 0 to (MapWidth-1) do begin
    for CountY := (MapHeight-1) downto 0 do begin
    //CurX and CurY are the Top Corners of the tiles
    CurX :=
    TopX - (TileWidth div 2) - CountX * (TileWidth div 2) + CountY * (TileWidth div 2);;
    CurY := TopY + CountY * (TileHeight div 2) + CountX * (TileHeight div 2);
    If (CurX >= ((TileWidth ) * - 1)) and (CurY >= 0) then begin
    With SourceRect do begin
    x := MapData[CountLayer*MapWidth*MapHeight+CountX*MapHeight+Cou ntY] * TileWidth;
    y := 0;
    h := TileHeight;
    w := TileWidth;
    end;
    With DestRect do begin
    x := CurX;
    y := CurY;
    h := TileHeight;
    w := TileWidth;
    end;

    SDL_BlitSurface(Tiles, @SourceRect, Scr, @DestRect);
    //Writeln('Blit''ed ',CountLayer,':',Countx,' ',countY, ' ', FormatDateTime('tt', now));
    end;
    end;
    end;
    end;

    end;

    Procedure CleanUp;
    var CountLayer: Word;
    begin
    For CountLayer := 0 to High(Layers) do sdl_FreeSurface(Layers[CountLayer]);
    end;

    begin
    //Writeln ('Initing SDL ', FormatDateTime('tt', now));
    SDL_Init(SDL_INIT_VIDEO); // Initialize the video SDL subsystem
    scr:=SDL_SetVideoMode(800 , 600, 16, SDL_SWSURFACE {or SDL_Fullscreen }{or SDL_DoubleBuf});
    stillrunning := true;
    SDL_WM_SetCaption('Caption', 'Icon');


    //Writeln ('Loading Map ', FormatDateTime('tt', now));
    LoadMap('Map1.map');

    //Writeln ('Loading Tiles ', FormatDateTime('tt', now));
    TileIn:= SDL_LoadBmp('Tiles.bmp');
    Tiles := SDL_DisplayFormat(TileIn);
    SDL_SetColorKey (Tiles, SDL_SRCColorKey or SDL_RLEAccel, SDL_MapRGB(Tiles.Format, 191, 123, 199));


    OffsetX := Scr^.W div 2;
    OffsetY := -256;

    //Writeln ('Drawing Map ', FormatDateTime('tt', now));
    DrawMapToBuf(OffsetX, OffsetY);
    SDL_Flip(Scr);

    leftPressed := false;
    rightPressed := false;
    upPressed :=false;
    downPressed :=false;

    while stillrunning do begin

    While SDL_PollEvent( @event ) > 0 do begin
    If Event.type_ = SDL_QUITEV then StillRunning := False;
    If Event.type_ = SDL_KEYDOWN then begin
    Case Event.key.keysym.sym of
    SDLK_Escape: StillRunning := False;
    SDLK_Up: upPressed := true;
    SDLK_Down: downPressed := true;
    SDLK_Left: leftPressed := true;
    SDLK_Right: rightPressed := true;
    end;

    end;

    If Event.type_ = SDL_KEYUP then begin
    Case Event.key.keysym.sym of
    SDLK_Escape: StillRunning := False;
    SDLK_Up: upPressed := false;
    SDLK_Down: downPressed := false;
    SDLK_Left: leftPressed := false;
    SDLK_Right: rightPressed := false;
    end;

    end;
    end;

    if upPressed then OffSetY := OffsetY + 96;
    if downPressed then OffSetY := OffsetY - 96;
    if leftPressed then OffsetX := OffsetX + 128;
    if rightPressed then OffsetX := OffsetX - 128;

    //Writeln('Keypress Detected ', FormatDateTime('tt', now));;
    DrawMapToBuf(OffsetX, OffsetY);
    //Writeln('Flipping ', FormatDateTime('tt', now));
    SDL_Flip(Scr);
    //Writeln('Done ', FormatDateTime('tt', now))

    end;

    CleanUp; // Deallocate pointers
    SDL_Quit; // close the subsystems and SDL

    end.

    [/pascal]

    Enjoy.

  5. #5

    Super Slow SDL (about 1/3 frame per second...)

    Whoa.... thankyou very much for that. Vast increase in speed - and I think I understand why. Thanks for your help.

    The rendering was put there just while I was learning SDL as part of the test - animation is the next thing I was going to try to do. As I can see you've moved the rendering anyway as part of fixing it - thanks for this. It should make the next step easier.

    Thankyou,


    lochok

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •