Page 1 of 3 123 LastLast
Results 1 to 10 of 28

Thread: Serious problems getting LockFPS to work.

  1. #1

    Serious problems getting LockFPS to work.

    I'm using a modified version of LockFPS and it only ever works properly while I'm stepping through the code.. as soon as I remove the break points, it stop working properly.

    [pascal]{$OPTIMIZATION OFF}
    function TSDLTicks.LockFPS(targetFPS: Byte): single;
    var
    currentTime : UInt32;
    TargetTime : UInt32;
    begin
    if (targetFPS = 0) then
    targetFPS := 1;


    // delay to maintain a constant frame rate
    currentTime :=SDL_GetTicks();
    if currentTime >m_FrameStartTime then
    begin

    TargetTime := m_FrameStartTime + (targetFPS *m_ticksPerSecond ) ;

    while true do
    begin

    currentTime :=SDL_GetTicks();

    if m_FrameStartTime - currentTime = 0 then
    begin
    SDL_Delay(1);
    end;

    if (currentTime<m_FrameStartTime) then
    begin
    result := 1;
    Break;
    end;

    result := currentTime / m_ticksPerSecond;
    if (TargetTime < currentTime) then
    begin
    result := 2;
    Break;
    end;
    end;
    end;

    m_FrameStartTime := currentTime;
    result := 0;
    end;[/pascal]

    I've been working on this all bloody day and I can't get it to work.

    FrameStartTime is set at the beginning of each cycle by calling a funciton on the class containing the LockFPS function.

    The LockFPS function is called at the end to eat up any spare CPU cycles and keep the game running at 30fps.

    I don't know WTF is happening and why it works perfectly when I step through, yet as soon as I remove the breakpoint and continue, it never exits the loop.
    I thought perhaps it was an optimization issue so I put the Optimization Off directive at the top of the unit and then at the top of the function, but it doesn't make any difference.

    This is also a problem when this is compiled using FPC.

    Any clues?

  2. #2

    Serious problems getting LockFPS to work.

    May be
    [pascal](targetFPS *m_ticksPerSecond)[/pascal]
    should be replaced with
    [pascal](m_ticksPerSecond / targetFPS)[/pascal]
    :?
    There are only 10 types of people in this world; those who understand binary and those who don't.

  3. #3

    Serious problems getting LockFPS to work.

    The code looks fine.. :?
    Maybe, just to make the code ‘safer’ instead using while True, make it as while Waiting and instead Break set Waiting:= false.
    [size=9px]BEGIN GEEK CODE BLOCK
    <br />d s-- : a24 GB GCS GTW GE C++ P L+ W++ N+ K- w++++ M- PS+ PE+ Y- t+ 5+++ X+ R*
    <br />tv b+ DI++ D+ e++ h+ G-
    <br />END GEEK CODE BLOCK[/size]
    <br />Create your own GeekCode block at: <a href="">...</a>

  4. #4

    Serious problems getting LockFPS to work.

    I've tried loads of combinations of this.. having the expression in the While loop itself, the original Until statement in the Jedi-SDL version does the same.

    All versions I try work when you step through and fail utterly when you don't

    I spent a long time banging my head against a brick wall on this.
    At first I thought it was being optimized to death.. but even with optimizing turned off, it still fails.

    I've tried putting SDL_Delay(1000) in there, nothing.. doesn't even seem to get called. I think Delphi is looking at the code and deciding that there's nothing to do in there and optimizing it out.. but when it steps through in the debugger, it has to follow each line. I dunno, I'm clutching at straws here.

  5. #5

    Serious problems getting LockFPS to work.

    Dr Bob says this..

    This is a Win32 Sleep function for a regular App.

    [pascal]
    procedure Sleep(MilliSecondsToWait: LongInt);
    var StartTime: LongInt;
    begin
    StartTime := GetTickCount;
    while (GetTickCount >= StartTime) and
    (GetTickCount < (StartTime + MilliSecondsToWait)) do
    Application.ProcessMessages
    end {Sleep};
    [/pascal]

    Unfortunately, there is no XPlatform ProcessMesseges function for SDL. The SDL_Delay might work, but it doesn't appear to be called..

    I'm going to try this with the GetTickCount function instead of the SDL_GetTicks

  6. #6

    Serious problems getting LockFPS to work.

    If your running on newish hardware also make sure that you are setting the thread affinity mask to 1 in your startup code. You may be running into the multiprocessor issues related to timmers and processes.

    Actually you should be doing this anyways, unless you are specifying the target processor for your timers. Another thing would be to do away with the locked FPS all together and make the application frame independent. Utilizing a rendering thread and a processing thread. You can then scale properly.

    Thread afinity mask code:
    [pascal] {$IFDEF WIN32}
    SetThreadAffinityMask(GetCurrentThread(), 1);
    {$ENDIF}
    [/pascal]

    Of final note, I've had problems with the SDL functions to get tick counts on some systems. To aliviate this I've created my own:
    [pascal]function SystemGetTickCount : Cardinal;
    begin
    result := -1;
    {$IFDEF WIN32}
    result := Windows.GetTickCount();
    {$ENDIF}
    {$IFDEF UNIX}
    result := clock_gettime(CLOCK_MONOTONIC);
    {$ENDIF}
    end;[/pascal]

    Well, ok, I didn't create my own, but I did wrap up the *NIX and Windows default calls so that one call would work on either OS. From testing the usage doesn't change. Still need to do the Mac version, but damned if I can find the right calls.

  7. #7

    Serious problems getting LockFPS to work.

    AAAARRRGGGHHHHHhhh Threads!!! (goes and hides under a box in the corner)

    I've not had much luck with Threads in the past, but that's probably because I've not had to use them much.

    Also, I've not written the engine to be thread safe so it'll probably fall over in a heap if I try to seperate the Logic and the rendering, Actually, they are quite seperate.. I call Engine.Tick( no#ticks ) followed by Engine.Render
    The Render looks through a list of renderable objects which are within the scope of the camera and draws them. ) but I think the change would be quite traumatic for the engine.

    For the time being, I'm going to press on with the FrameLocking style of coding.

    I am starting to look into more frame independant technique however as it works well on slower machines.. at the moment it's a crude multiply by missed ticks technique, but it could be improved.


    Also, I'm working on a fairly old 800 Athlon machine.. single processor. But I'll look into that Thread/processor issue.

  8. #8

    Serious problems getting LockFPS to work.

    The following code should ( tested in a console app ) lock your FPS to a TargetFPS.

    [pascal]
    procedure TSDLTicks.LockFPS(targetFPS: Byte);
    var
    currentTime : UInt32;
    targetTime : single;
    begin
    if (targetFPS = 0) then
    targetFPS := 1;

    targetTime := m_ticksPerSecond / targetFPS;

    // delay to maintain a constant frame rate
    repeat
    currentTime := SDL_GetTicks;
    until ( (currentTime - s_lastTime ) > targetTime );

    // reset the timer
    s_lastTime := currentTime;
    end;
    [/pascal]
    <br /><br />There are a lot of people who are dead while they are still alive. I want to be alive until the day I die.<br />-= Paulo Coelho =-

  9. #9

    Serious problems getting LockFPS to work.

    Cheers Dom, I'll give this a test later.

    One thing though, the LockFPS function has to be capable of withstanding the rollover (Apparently the SDL_GetTicks rolls back after 40 odd days) if this isn't taken into account, when the rollover happens, the game will lock up.

    A simple test to see if the CurrentTime < s_LastTime will do.

  10. #10

    Serious problems getting LockFPS to work.

    According to the source code...
    Get the number of milliseconds since the SDL library initialization.
    Note that this value wraps if the program runs for more than ~49 days.
    My understanding is that, this is essentially since the game/app started.
    If someone is still playing your games after 49 days straight, it's either the best game ever and/or the gamer does not have much of a social life
    <br /><br />There are a lot of people who are dead while they are still alive. I want to be alive until the day I die.<br />-= Paulo Coelho =-

Page 1 of 3 123 LastLast

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
  •