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

Author Topic: How to achieve high framerate with Vertical Sync?  (Read 5641 times)

0 Members and 1 Guest are viewing this topic.

kolofsson

  • Full Member
  • ***
  • Posts: 100
    • View Profile
How to achieve high framerate with Vertical Sync?
« on: November 06, 2011, 11:09:06 pm »
Hi. If I am correct, enabling vertical sync pauses the app each time window.display() is called, so that the buffer is not overwritten while the graphics card renders it. This means that the main game loop will be repeated the number of times equal to the refresh rate (e.g. 60).

What if I wanted to achieve more calculation frames per second (e.g. I'm making an F1 game and I want to count lap times in milliseconds, or I make a multiplayer game and I want to process the data from sockets the moment they arrive)?

Would multi-threading be an option? 1 thread for physics calculations, other thread for rendering stuff? Would vsync even work if I did not lock the window.display() method?

Also, what happens if Vsync is enabled to 60 FPS (new frame is rendered every 17 milliseconds) but my main game loop lasts a constant 20 ms? Will SFML "miss the train" and wait to catch the next one (34 ms), thus reducing the effective framerate to 30 FPS?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
How to achieve high framerate with Vertical Sync?
« Reply #1 on: November 06, 2011, 11:52:02 pm »
Quote
Would multi-threading be an option?

The only one.

Quote
Also, what happens if Vsync is enabled to 60 FPS (new frame is rendered every 17 milliseconds) but my main game loop lasts a constant 20 ms? Will SFML "miss the train" and wait to catch the next one (34 ms), thus reducing the effective framerate to 30 FPS?

Yes. But it's not SFML, it's the graphics card's driver.
Laurent Gomila - SFML developer

kolofsson

  • Full Member
  • ***
  • Posts: 100
    • View Profile
How to achieve high framerate with Vertical Sync?
« Reply #2 on: November 07, 2011, 09:59:39 am »
Quote from: "Laurent"
Quote
Would multi-threading be an option?

The only one.


OK, so if threading it is, then let me ask once more:
Would Vsync work if I did not lock the thread while calling window.display()? Clearly, locking the thread would be missing the point, since the delay is caused by window.display(). On the other hand, I'm not sure what would happen if I interrupted while it was running. Would it not be like jumping out of a train? :D. I wonder how big is the gap that the graphics card leaves between each frame for apps to fill the buffer, compared to the time that takes to fill the buffer.

I think some kind of boolean would be useful, like Is_Buffer_Being_Used or Is_It_Safe_To_Fill_The_Buffer_Now . Then, after checking one of these, I could safely lock the thread until window.display() finishes it's work.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
How to achieve high framerate with Vertical Sync?
« Reply #3 on: November 07, 2011, 10:30:22 am »
If you use multiple threads, it would be one for rendering, and one for other calculations that need higher rate. So as long as all the rendering commands are in the same thread, you don't have to worry about multithreading issues with window.Display().
Laurent Gomila - SFML developer

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
How to achieve high framerate with Vertical Sync?
« Reply #4 on: November 07, 2011, 11:13:22 am »
When doing your threading you can keep in mind that a lag up to two frames are actually acceptable if not expected from the users point of view. It has existed in games for so long so that some games can feel too responsive (your brain automatically calculates for the delay). So if the graphics coming to the screen is 1-2 frames old it doesn't matter.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

kolofsson

  • Full Member
  • ***
  • Posts: 100
    • View Profile
How to achieve high framerate with Vertical Sync?
« Reply #5 on: November 07, 2011, 12:24:19 pm »
Guys, thanks for the feedback, I appreciate it :).

What if I don't lock the rendering thread and it will get interrupted in the middle of executing window.display() and switch to the calculation thread? What if the graphics card decides to render the buffer to the screen in that particular moment? Will it result in display tearing, thus negating the effect of Vsync for that frame? Or maybe the window.display() method contains some mutex inside it that prevents interruption while filling the screen?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
How to achieve high framerate with Vertical Sync?
« Reply #6 on: November 07, 2011, 12:31:03 pm »
Don't worry about that, it's handled inside the graphics card so there's no chance that the physical operation of displaying the current frame gets interrupted. This is a very low-level task which is entirely handled by the hardware.
Laurent Gomila - SFML developer

kolofsson

  • Full Member
  • ***
  • Posts: 100
    • View Profile
How to achieve high framerate with Vertical Sync?
« Reply #7 on: November 20, 2011, 02:31:22 pm »
Hi Laurent. I tried doing this with threads but I found it too complicated.

Instead I created an IF inside the main loop which omits the display method until it is very close to Vsync. Thanks to this trick the main loop runs 6000 times per second instead of 60.

Code: [Select]
def main():
   window = sf.RenderWindow(sf.VideoMode(800, 600), 'Window', sf.Style.DEFAULT)
   window.vertical_sync_enabled = True

   last_display = time.clock()
   while window.opened:      
      for event in window.iter_events():
         #handle events

      if time.clock() - last_display > 0.016:
         window.clear(sf.Color(200,   0,   0))
         window.display()
         last_display = time.clock()


The problem is, I set the value 0.016 to just under 1/60 of a second, which is suitable for a refresh rate of 60 Hz. With a different refresh rate it would be a disaster as the display would miss every second frame and wait twice as long.

So I have a few questions:
1. Is it possible to get the screen's refresh rate with SFML? The one that is used when Vsync is on.
2. If not, would it be difficult to implement a renderwindow.GetFramerate?
3. Do SetFramerateLimit and EnableVerticalSync override each other?
4. When initializing a window in full screen, is it possible to select a refresh rate? For example my display can work in 60 Hz or 75Hz for certain resolutions.
4. Should not screen refresh rate be a part of VideoMode?

A perfect solution for me would be:
- get list of video modes, together with refresh rate
- initialize a window e.g. (800,600,fullscreen,refresh_rate=60)
- enable vertical sync

Then I would know the refresh rate and could set my code based on that.