• 13
• 16
• 27
• 9
• 9

# Restricting fps of engine

This topic is 4474 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Using OGL (don't know if this matters), when I'm restricting the fps of my engine, and I don't render a frame on any particular iteration of the main loop, I should not be calling "SwapBuffers(hDC)". Is this right? If so, I have a small problem. I have the code to restict the fps in the scene graph class. Should it go into the video driver (basically a wrapper for OGL) class?

##### Share on other sites
My approach would be to create a frame limiter module independent from the graphics API. Assuming that frame rendering is correctly encapsulated in your engine, one of your threads will be doing an operation similar to the following:

[Do non-rendering things] [Start frame rendering] [Render] [Present frame] [Do rendering-related things][End frame rendering][Do non-rendering things]

Where non-rendering things are not related to rendering in any way. Then, a simple transformation is to perform, instead:

[Do non-rendering things]if( frameLimiter.NextFrame( ) ) {  frameLimiter.StartFrame( );   [Start frame rendering]   [Render]   [Present frame]   [Do rendering-related things]  [End frame rendering]}[Do non-rendering things]

By making the frame limiter independent from your renderer code or your driver code, you make it more reusable (it could be used to limit things other than frames, such as updates or logic steps for certain objects) and more easily maintained, replaced, debugged and tested.

##### Share on other sites
Quote:
 Original post by ToohrVyk[Start frame rendering] [Render] [Present frame]

If by "present frame" you mean "swap buffers" I would have to strongly disagree. Unless I am completely mixing things up a buffer swap will block until the swap actually happened. Which means that if you issue all your draw calls and then immediately swap buffers you would waste a ton of cpu time sitting around and doing nothing while waiting for the gpu to get its act together and finish the frame. I tend to swap buffers right BEFORE I start throwing work at the gpu, to make sure all preparations for the next frame are done while the current frame is rendered.

Experiment: draw a dozen screen filling quads and use a complex fragment shader, just to make the scene will take a while. Then place the buffer swap right after the draw call. After that, waste some time on calculating a few million random square roots (make sure they aren't optimized away, sum them together and print the result or something). Check the fps. Then move the buffer swap until AFTER the square roots and check again. Not sure if D3D allowed non-blocking buffer swaps. Using occlusion queries is making it even more fun to put them in the "best" place.

##### Share on other sites
How you organize your rendering code is up to you. I was only pointing out an example of separation between rendering code and non-rendering code, and I think anyone can agree other examples exist. However, even though it can be more efficient to issue a buffer swap command before rendering the next frame, presenting is a logical part of a frame. Since you can neither present a frame without rendering it nor finish a frame until it is presented, it makes sense to have the same code perform the two operations, even if they are executed at different times. So you can interpret my "present frame" operation as "swap buffers now" on platforms without a GPU or a blocking swap operation, and as "schedule buffer swap" on platforms where the swap operation is blocking. The two are semantically the same, and only differ in their efficiency, which is irrelevant here.

##### Share on other sites
Also Euler integration is un-accurate when the time frames differ so you can for example split delta up into time steps

// Where DeltaTime is in milliseconds
Steps = DeltaTime * 1000;

For (int g=0;g < Steps;g++)
DoPhysics(g / 1000);
Thus for each millisecond there is a time frame

Or you can make it more realistic with about a time frame for each 20 milliseconds, simple change 1000 to 1000/20.

Oh and ofcourse the left over Time is carried over to the next call.