Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Is SetFramerateLimit() actually useful? [in respect to its issues]  (Read 3110 times)

0 Members and 1 Guest are viewing this topic.

aljowen

  • Newbie
  • *
  • Posts: 2
    • View Profile
Hi,
Enabling the frame rate limit in SFML is inaccurate, as I have found both via the wiki and my own testing (admittedly I have only checked under windows).

From my own testing I can see that it is only accurate to integer milliseconds. Which isn't ideal for the very reasons stated on the wiki. In my testing it sits at 67fps when set to 60fps, with accuracy getting entertainingly worse the higher the limit is set.
Since the above is similar to what the wiki suggests to expect (and that vsync works as expected), I am assuming I have things set up correctly on my end.

However, if that were the only issue, it probably wouldn't be so bad (for certain use cases). But enabling a framerate limit also seems to cause massive jumping issues for objects that should be moving at a fixed speed across the screen (or panning the camera etc). Its quite visually jarring.


So, obviously, a programmer can work around this by writing their own frame limiter. But that leaves me wondering:
 a) If the issue is windows specific, should there be some windows specific code built into the library to address the issue?
 b) If not, should the feature actually exist as part of the library?

To elaborate on "b)", is it really a useful feature to have, if it isn't crossplatform functional, is inaccurate, and could easily lead to bugs in sfml based software.



Hopefully this post doesn't come across too negatively, I really do enjoy working in SFML, it is a really excellent library. This is just one of those things that seems kinda odd to me.

Hapax

  • Hero Member
  • *****
  • Posts: 3346
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Is SetFramerateLimit() actually useful? [in respect to its issues]
« Reply #1 on: May 07, 2019, 06:14:59 pm »
It is inaccurate.
Remember, though, that it isn't there to set a specific frame rate. It is to limit the amount of frames being unnecessarily being processed.
You can consider it a way to have an approximate frame length by allowing the program to sleep between frames. This can be important for a number of reasons. For example, freeing up processor threads to help the OS to multitask and reducing the amount of battery used on portable devices.

The "visually jarring" "jumping issue" should be easily avoidable by setting the framerate limit to higher than the monitor's refresh rate, moving the object based on the time passed and also interpolating frames for partial fixed-delta frame times.
These have been mentioned on these forums a number of times and wouldn't be too difficult to find by using the forum's search.

Another option is to just use v-sync. As long as you can be sure that the graphics drivers actually set the v-sync, this can be by some considered the better option. Remember to never use the two together.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

aljowen

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Is SetFramerateLimit() actually useful? [in respect to its issues]
« Reply #2 on: May 07, 2019, 10:03:31 pm »
So for your first two paragraphs. I am aware of why limiting is desirable. While I have only been using SFML for about a year now, I had been using SDL for two years prior (both with its internal renderer and OpenGL). SDL seems to keep its 60fps reliably, while SFML does not. (example code at the bottom of post, to show that I wasn't spinning hot to achieve this)

For context I am working in game development.

I give the player the option to enable v-sync, the frame rate limiter, or neither. That is their choice to make (although I do prevent both from being used concurrently, because that would be plain bad). In my case the player has control over what frame rate limit they wish to use. Typically players will set the frame rate limit to that of their monitors refresh rate. They do this to combat tearing. While a good 60fps limiter won't stop tearing, it will greatly reduce its visual appearance without the drawbacks of vsync. Hence many gamers consider it to be a more desirable option than vsync.

Since my game runs anywhere from 20fps to "infinite fps", movement is interpolated based upon frame timings. Obviously it runs smooth without limiting, it also runs smooth with vsync enabled (60fps on my monitor), but with the limiter enabled at 60fps it gets visibly choppy.

Now while v-sync is an option, v-sync isn't perfect, since it adds a slight delay to the rendering, which some people find uncomfortable to use, especially with regards to mouse movement. Of course, I could use the native windows mouse pointer, but then UI collision detection is one frame behind the current mouse location on screen, leading to clicks being registered in the wrong place. Which can be quite frustrating.


Hence, I find myself wondering if SFML's frame rate limiter is currently fit for purpose? However, I must admit, when I made the OP, I had mistakenly assumed that SFML would have a similar feature to SDL where you can tell it to sleep, upon further inspection it does not seem to. As such there isn't currently any "just works" way to do better.
So my guess would be that the only real solution is to manually time how long SFML waited for on the last frame. Then set the FPS limit each frame to purposefully undershoot slightly, and then spin hot in a while loop until the correct time is achieved.
Its hardly the end of the world, but it doesn't feel that elegant (or simple) either xD





if (frameLimiter == true){
   //time: time taken to run the game code (get time before running code, get time after running code, subtract them)
   //frameTarget: whatever fps is being targeted (ie, 60)

   //If time is negative, the time probably overflew, ignore it and continue
   if (time < 0) continue;

   //Subtract the "framerate target" by the "time taken to run the game code"
   float sleepTime = (1.0 / (float)frameTarget) - (time);
   if (sleepTime > 0)
   {
      //Tell SDL to sleep until the next frame is due
      SDL_Delay(sleepTime);
   }
   else
   {
      //The game took longer to run than the target, begin next frame immediately without delay
   }
}
« Last Edit: May 07, 2019, 10:06:36 pm by aljowen »

 

anything