SDL_SetVideoMode ignores flags & SDL_Flip is slow - sdl

I'm initializing with
SDL_Init(SDL_INIT_VIDEO);
screen = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE|SDL_DOUBLEBUF);
and then calling, in a loop, between calls to sleep, just
SDL_LockSurface(screen);
// Will eventually twiddle pixels here...but not yet
SDL_UnlockSurface(screen);
SDL_Flip(screen);
And that call to flip takes a varying amount of time, but around 10ms, which is a lot for nothing.
So that makes me wonder if I'm causing, say, a copy from video memory to system memory or something, and I should create the surface differently. BUT, additionally, screen->flags is always equal to SDL_ASYNCBLIT and no other bits are set, regardless of the flags I pass to SDL_SetVideoMode. So I can't make any other kind of surface anyway.
Should I be creating another offscreen surface, rendering to that, and then blitting it to the screen? What am I doing wrong?
EDIT: Removing the SDL_Lock and SDL_Unlock pair does nothing to speed things up. The SDL_Flip is just slow.

For the sake of the two or three people that may, someday, see this question, I think the reason the SDL_Flip takes so long is that it waits for vsync, so a busy loop calling SDL_Flip will necessarily be limited by the vsync rate.
If that's correct, the fact that SDL_Flip takes so long is not an actual issue, since if I were doing work to render things, then there'd be less time to wait for the vsync.

I use Win7, Codeblocks/MingW, SDL 1.2.14. Grumdrig said:
For the sake of the two or three people that may, someday, see this
question, I think the reason the SDL_Flip takes so long is that it
waits for vsync, so a busy loop calling SDL_Flip will necessarily be
limited by the vsync rate.
If that's correct, the fact that SDL_Flip takes so long is not an
actual issue, since if I were doing work to render things, then
there'd be less time to wait for the vsync.
Nah, something is wrong. My programs performed fine until relatively recently, and I spent awhile myself today looking for the cause of my own bottleneck, which turned out to be SDL_Flip() like yours, which led me to your question through a google search. Interestingly enough, on my older WinXP single core the performance is better, so my guess is that the problem is caused by the friendly Win7 auto-updates. Perhaps Microsoft is unintentionally de-optimizing the GDI!
In any case, SDL_Flip shouldn't take so long to resolve itself, and in case anyone is wondering, I put a Uint32 SDL_Getticks() timer above SDL_Flip() and outputted the length below if it was over 5 ms. The result was numbers like 27, 59 and 88 milliseconds from time to time, which is not good. And of course, the problem is the same whether I use SWSURFACE or HWSURFACE as the flag to SetVideoMode.
Before I leave a comment on the SDL website I may try rebuilding with SDL 1.2.15, though that might require a rebuild of SpriG, so I'm not in a rush. But in general, I stand by what I said: chances are, it's a Win7 thing, if that's your operating system.
Addendum 5:17 PM EST: I just compiled and ran a smaller, unrelated project that uses SDL 1.2.15 and the problem was the same: normal smooth movement followed by occasional jerks. Testing for only when SDL_Flip() took more than 5 milliseconds, the output included values ranging from 30 to over 60 milliseconds, which would happen about once every second or two.
Addendum 5-8-12: On 5-4-12 there was a big thunderstorm and I had to turn off and unplug the computer, with the result that the next day SDL_Flip() always took under 5ms, so the problem is solved now.

Related

Reliable windowed vsync with OpenGL on Windows?

SUMMARY
It seems that vsync with OpenGL is broken on Windows in windowed mode. I've tried different APIs (SDL, glfw, SFML), all with the same result: While the framerate is limited (and consistently around 16-17 ms according to CPU measurements on multiple 60 Hz setups I've tried), and the CPU is in fact sleeping most of the time, frames are very often skipped. Depending on the machine and the CPU usage for things other than rendering, this can be as bad as effectively cutting the frame rate in half. This problem does not seem to be driver related.
How to have working vsync on Windows with OpenGL in windowed mode, or a similar effect with these properties (if I forgot something notable, or if something is not sensible, please comment):
CPU can sleep most of the time
No tearing
No skipped frames (under the assumption that the system is not overloaded)
CPU gets to know when a frame has actually been displayed
DETAILS / SOME RESEARCH
When I googled opengl vsync stutter or opengl vsync frame drop or similar queries, I found that many people are having this issue (or a very similar one), yet there seems to be no coherent solution to the actual problem (many inadequately answered questions on the gamedev stackexchange, too; also many low-effort forums posts).
To summarize my research: It seems that the compositing window manager (DWM) used in newer versions of Windows forces triple buffering, and that interferes with vsync. People suggest disabling DWM, not using vsync, or going fullscreen, all of which are not a solution to the original problem (FOOTNOTE1). I have also not found a detailed explanation why triple buffering causes this issue with vsync, or why it is technologically not possible to solve the problem.
However: I've also tested that this does not occur on Linux, even on VERY weak PCs. Therefore it must be technically possible (at least in general) for OpenGL-based hardware acceleration to have functional vsync enabled without skipping frames.
Also, this is not a problem when using D3D instead of OpenGL on Windows (with vsync enabled). Therefore it must be technically possible to have working vsync on Windows (I have tried new, old, and very old drivers and different (old and new) hardware, although all the hardware setups I have available are Intel + NVidia, so I don't know what happens with AMD/ATI).
And lastly, there surely must be software for Windows, be it games, multimedia applications, creative production, 3D modeling/rendering programs or whatever, that use OpenGL and work properly in windowed mode while still rendering accurately, without busy-waiting on the CPU, and without frame drops.
I've noticed that, when having a traditional rendering loop like
while (true)
{
poll_all_events_in_event_queue();
process_things();
render();
}
The amount of work the CPU has to do in that loop affects the behavior of the stuttering. However, this is most definitely not an issue of the CPU being overloaded, as the problem also occurs in one of the most simple programs one could write (see below), and on a very powerful system that does nothing else (the program being nothing other than clearing the window with a different color on each frame, and then displaying it).
I've also noticed that it never seems to get worse than skipping every other frame (i.e., in my tests, the visible framerate was always somewhere between 30 and 60 on a 60 Hz system). You can observe somewhat of a Nyquist sampling theorem violation when running program that changes the background color between 2 colors on odd and even frames, which makes me believe that something is not synchronized properly (i.e. a software bug in Windows or its OpenGL implementation). Again, the framerate as far as the CPU is concerned is rock solid. Also, timeBeginPeriod has had no noticeable effect in my tests.
(FOOTNOTE1) It should be noted though that, because of the DWM, tearing does not occur in windowed mode (which is one of the two main reasons to use vsync, the other reason being making the CPU sleep for the maximum amount of time possible without missing a frame). So it would be acceptable for me to have a solution that implements vsync in the application layer.
However, the only way I see that being possible is there is a way to explicitly (and accurately) wait for a page flip to occur (with possibility of timeout or cancellation), or to query a non-sticky flag that is set when the page is flipped (in a way that doesn't force flushing the entire asynchronous render pipeline, like for example glGetError does), and I have not found a way to do either.
Here is some code to get a quick example running that demonstrates this problem (using SFML, which I found to be the least painful to get to work).
You should see homogenous flashing. If you ever see the same color (black or purple) for more than one frame, it's bad.
(This flashes the screen with the display's refresh rate, so maybe epilepsy warning):
// g++ TEST_TEST_TEST.cpp -lsfml-system -lsfml-window -lsfml-graphics -lGL
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
#include <iostream>
int main()
{
// create the window
sf::RenderWindow window(sf::VideoMode(800, 600), "OpenGL");
window.setVerticalSyncEnabled(true);
// activate the window
window.setActive(true);
int frame_counter = 0;
sf::RectangleShape rect;
rect.setSize(sf::Vector2f(10, 10));
sf::Clock clock;
while (true)
{
// handle events
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
return 0;
}
}
++frame_counter;
if (frame_counter & 1)
{
glClearColor(0, 0, 0, 1);
}
else
{
glClearColor(60.0/255.0, 50.0/255.0, 75.0/255.0, 1);
}
// clear the buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Enable this to display a column of rectangles on each frame
// All colors (and positions) should pop up the same amount
// This shows that apparently, 1 frame is skipped at most
#if 0
int fc_mod = frame_counter % 8;
int color_mod = fc_mod % 4;
for (int i = 0; i < 30; ++i)
{
rect.setPosition(fc_mod * 20 + 10, i * 20 + 10);
rect.setFillColor(
sf::Color(
(color_mod == 0 || color_mod == 3) ? 255 : 0,
(color_mod == 0 || color_mod == 2) ? 255 : 0,
(color_mod == 1) ? 155 : 0,
255
)
);
window.draw(rect);
}
#endif
int elapsed_ms = clock.restart().asMilliseconds();
// NOTE: These numbers are only valid for 60 Hz displays
if (elapsed_ms > 17 || elapsed_ms < 15)
{
// Ideally you should NEVER see this message, but it does tend to stutter a bit for a second or so upon program startup - doesn't matter as long as it stops eventually
std::cout << elapsed_ms << std::endl;
}
// end the current frame (internally swaps the front and back buffers)
window.display();
}
return 0;
}
System info:
Verified this problem on these systems:
Windows 10 x64 i7-4790K + GeForce 970 (verified that problem does not occur on Linux here) (single 60 Hz monitor)
Windows 7 x64 i5-2320 + GeForce 560 (single 60 Hz monitor)
Windows 10 x64 Intel Core2 Duo T6400 + GeForce 9600M GT (verified that problem does not occur on Linux here) (single 60 Hz laptop display)
And 2 other people using Windows 10 x64 and 7 x64 respectively, both "beefy gaming rigs", can request specs if necessary
UPDATE 20170815
Some additional testing I've done:
I tried adding explicit sleeps (via the SFML library, which basically just calls Sleep from the Windows API while ensuring that timeBeginPeriod is minimal).
With my 60 Hz setup, A frame should ideally be 16 2/3 Hz. According to QueryPerformanceCounter measurements, my system is, most of the time, very accurate with those sleeps.
Adding a sleep of 17 ms causes me to render slower than the refresh rate. When I do this, some frames are displayed twice (this is expected), but NO frames are dropped, ever. The same is true for even longer sleeps.
Adding a sleep of 16 ms sometimes causes a frame to be displayed twice, and sometimes causes a frame to be dropped. This is plausible in my opinion, considering a more or less random combination of the result at 17 ms, and the result at no sleep at all.
Adding a sleep of 15 ms behaves very similarly to having no sleep at all. It's fine for a short moment, then about every 2nd frame is dropped. The same is true for all values from 1 ms to 15 ms.
This reinforced my theory that the problem might be nothing other than some plain old concurrency bug in the vsync logic in the OpenGL implementation or the operating system.
I also did more tests on Linux. I hadn't really looked much into it before - I merely verified that the frame drop problem didn't exist there and that the CPU was, in fact, sleeping most of the time. I realised that, depending on several factors, I can make tearing consistenly occur on my test machine, despite vsync. As of yet, I do not know whether this that issue is connected to the original problem, or if it is something entirely different.
It seems like the better approach would be some gnarly workarounds and hacks, and ditching vsync altogether and implementing everything in the application (because apparently in 2017 we can't get the most basic frame rendering right with OpenGL).
UPDATE 20170816
I have tried to "reverse-engineer" a bunch of open source 3D engines (got hung up on obbg (https://github.com/nothings/obbg) in particular).
First, I checked that the problem does not occur there. The frame rate is butter smooth. Then, I added my good old flashing purple/black with the colored rects and saw that the stuttering was indeed minimal.
I started ripping out the guts of the program until I ended up with a simple program like mine. I found that there is some code in obbg's rendering loop that, when removed, causes heavy stutter (namely, rendering the main part of the obbg ingame world). Also, there is some code in the initialization that also causes stutter when removed (namely, enabling multisampling). After a few hours of fiddling around it seems that OpenGL needs a certain amount of workload to function properly, but I have yet to find out what exactly needs to be done. Maybe rendering a million random triangles or something will do.
I also reaslised that all my existing tests behave slightly differently today. It seems that I have overall fewer, but more randomly distributed frame drops today than the days before.
I also created a better demo project that uses OpenGL more directly, and since obbg used SDL, I also switched to that (although I briefly looked over the library implementations and it would surprise me if there was a difference, but then again this entire ordeal is a surprise anyway). I wanted to approach the "working" state from both the obbg-based side, and the blank project side so I can be really sure what the problem is. I just put all the required SDL binaries inside the project; if as long as you have Visual Studio 2017 there should be no additional dependencies and it should build right away. There are many #ifs that control what is being tested.
https://github.com/bplu4t2f/sdl_test
During the creation of that thing I also took another look how SDL's D3D implementation behaves. I had tested this previously, but perhaps not quite extensively enough. There were still no duplicate frames and no frame drops at all, which is good, but in this test program I implemented a more accurate clock.
To my surprise I realised that, when using D3D instead of OpenGL, many (but not the majority) loop iterations take somewhere between 17.0 and 17.2 ms (I would not have caught that with my previous test programs). This does not happen with OpenGL. The OpenGL rendering loop is consistently in the range 15.0 .. 17.0. If it is true that sometimes there needs to be a slightly longer waiting period for the vertical blank (for whatever reason), then OpenGL seems to miss that. That might be the root cause of the entire thing?
Yet another day of literally staring at a flickering computer screen. I have to say I really did not expect to spend that amount of time on rendering nothing but a flickering background and I'm not particularly fond of that.

What is the accepted timing strategy when using Vertical Synchronisation?

Coming from a basic understanding of OpenGL programming, all required drawing operations are performed in a sequence, once per frame redraw. The performance of the hardware dictates essentially how fast this happens. As I understand, a game will attempt to draw as quickly as possible so redraw operations are essentially wrapped in a while loop. The graphics operations (graphics engine) will then be optimised to ensure the frame rate is acceptable for the application.
Graphics hardware supporting Vertical Synchronisation however locks frame rates to the display rate. A first question would be how should a graphics engine interact with the hardware synchronisation? Is this even possible or does the renderer work at maximum speed and the hardware selectively calls up the latest frame, discarding all unused previous frames..?
The motivation for this question is not that I am immediately intending to write a graphics engine, instead am debugging an issue with an existing system where the graphics of a moving scene appear to stutter onscreen. Symptomatically, the stutter is slight when VSync is turned off, when it is turned on either there is a significant and periodic stutter or alternatively the stutter is resolved entirely. I am somewhat clutching at straws as to what is happening or why, want to understand some more background information on graphics systems.
Summarily the question would be on how one is expected to interact with hardware redraw events and if that is even possible. However any additional information would be welcome.
A first question would be how should a graphics engine interact with the hardware synchronisation?
To avoid flicker modern rendering systems use double buffering i.e. there are two color plane buffers and after finishing drawing to one, the display readout pointer is set to the finished buffer plane. This buffer swap can happen synchronized or non-synchronized. With V-Sync enabled the buffer swap will be synchronized and the rendering thread blocks until the buffer swap happened.
Since with double buffering mandates buffer swaps this implicitly introduces a synchronization mechanism. This is how interactive rendering systems lock onto the display refresh.
Symptomatically, the stutter is slight when VSync is turned off, when it is turned on either there is a significant and periodic stutter or alternatively the stutter is resolved entirely.
This sounds like a badly written animation loop that assumes constant framerate locked onto the display refresh rate, based on the assumption that frames render faster than a display refresh interval and the buffer swap can be issued in time for the next retrace to happen.
The only robust way to deal with vertical synchronization is to actually measure the time between frame renderings and advance the rendering loop by that amount of time.
This is a guess, but:
The Problem Isn't Vertical Synchronization
I don't know what OS you're working with, but there are various ways to get information about the monitor and how fast the screen is refreshing (for the purposes of this answer, we'll assume your monitor is somewhat recent and redraws at a rate of 60 Hz, or 60 times every second, or once every 16.66666... milliseconds).
Renderers are usually paired up with an "Logic" side to the application: input, ui calculations, simulation running, etc. etc. It seems like the logic side of your application is running fast enough, but the Rendering side - i.e., the Draw Call as its commonly summed up into - is bounding the speed of your application.
Vertical Synchronization can exacerbate this in that if your Draw Call is made to happen every 16.66666 milliseconds - but it takes much longer than 16.666666 milliseconds - then you perceive a frame rate drop (i.e. frames will "stutter" because they're taking too long to produce a single frame). VSync - and the enabling or disabling thereof - is not something that bottlenecks your code: it just says "hey, since the Hardware is only going to take 1 frame from us every 16.666666 milliseconds, why make more draw calls than just one every 16.66666 milliseconds? As long as we do one draw call once for every passing of this time, our application will look as fluid as possible, and we don't have to waste time making more calls than that!"
The problem with that is that it assumes your code is going to run fast enough to make it in those 16.6666 milliseconds. If it does not, stuttering, lagging, visual artifacts, frozen frames, and other things manifest themselves on screen.
When you turn off VSync, you're telling your Render Call to be called as often as possible, as fast as possible. This may give it some extra wiggle room alongside the Logic call to get a frame rendered, so that when the Hardware Says "I'm gonna take a picture and put it on the screen now!" it's all prettied up, just in time, to get into posture and say cheese! (though by what you say, it barely makes it).
What To Do:
Start by profiling your code. Find out what functions are taking the most time. Judging by the stutter, something in your code is taking longer than is expected and is giving you undesirable performance. Make sure to profile first to find the critical sections of where you're burning away time, and figure out how to keep it correct and make it just as fast. You may want to figure out what's being called in the Render Call and profile the time it takes to complete one cycle of that specifically. Then time the Logic call(s) and see how long it takes to execute those as well. Then, chop away.
Good luck!

Weird CPU usage in OpenGL program

In an MFC-program I built myself I have some weird problems with the CPU usage.
I load a point cloud of around 360k points and everything works fine (I use VBO buffers which is the way to do it from what I understand?). I can move it around as I please and notice no adverse effects (CPU usage is very low, GPU does all the work). But then at certain angles and zoom values I see the CPU spike on one of my processors! I can then change the angle or zoom a little and it will go down to around 0 again. This is more likely to happen in a large window than a small one.
I measure the FPS of the program and it's constantly at 65, but when the CPU spike hits it typically goes down around 10 units to 55. I also measure the time SwapBuffers take and during normal operation it's around 0-1 ms. Once the CPU spike hits it goes up to around 20 ms, so it's clear something suddenly gets very hard to calculate in that function (for the GPU I guess?). This something is not in the DrawScene function (which is the function one would expect to eat CPU in a poor implementation), so I'm at a bit of a loss.
I know it's not due to the number of points visible because this can just as easily happen on just a sub-section of the data as on the whole cloud. I've tried to move it around and see if it's related to the depth buffer, clipping or similar but it seems entirely random what angles create the problem. It does seem somewhat repeatable though; moving the model to a position that was laggy once will be laggy when moved there again.
I'm very new at OpenGL so it's not impossible I've made some totally obvious error.
This is what the render loop looks like (it's run in an MFC app via a timer event with 1 ms period):
// Clear color and depth buffer bits
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw OpenGL scene
OGLDrawScene();
unsigned int time1 = timeGetTime();
// Swap buffers
SwapBuffers(hdc);
// Calculate execution time for SwapBuffers
m_time = timeGetTime() - time1;
// Calculate FPS
++m_cnt;
if (timeGetTime() - m_lastTime > 1000)
{
m_fps = m_cnt;
m_cnt = 0;
m_lastTime = timeGetTime();
}
I've noticed that (at least a while back), ATI drivers tend to like to spin-wait a little too aggressively, while NVidia drivers tend to be interrupt driven. Technically spin-waiting is faster, assuming you have nothing better to do. Unfortunately, today you probably do have something better to do on another thread.
I think the OP's display drivers may indeed be spin-waiting.
Ok, so I think I have figured out how this can happen.
To begin with the WM_TIMER messages doesn't seem to be generated more often than every 15 ms at best, even when using timeBeginPeriod(1), at least on my computer. This resulted in the standard 65 fps I was seeing.
As soon as the scene took more than 15 ms to render, SwapBuffers would be the limiting factor instead. SwapBuffers seem to busy-wait, which resulted in 100% CPU usage on one core when this happened. This is not something that occurred at certain camera angles, but is a result of a fluidly changing fps depending on how many points were shown on the screen at the time. It just appeared to spike whenever rendering happened to hit a time over 15 ms and started to wait at SwapBuffers instead.
On a similar note, does anyone know of a function like "glReadyToSwap" or something like that? A function that indicates if the buffers are ready to be swapped? That way I could choose another method for rendering with a higher resolution (1 ms for example) and then each ms check if the buffers are ready to swap, if they aren't just wait another ms, so as to not busy-wait.

setting max frames per second in openGL

Is there any way to calculate how much updates should be made to reach desired frame rate, NOT system specific? I found that for windows, but I would like to know if something like this exists in openGL itself. It should be some sort of timer.
Or how else can I prevent FPS to drop or raise dramatically? For this time I'm testing it on drawing big number of vertices in line, and using fraps I can see frame rate to go from 400 to 200 fps with evident slowing down of drawing it.
You have two different ways to solve this problem:
Suppose that you have a variable called maximum_fps, which contains for the maximum number of frames you want to display.
Then You measure the amount of time spent on the last frame (a timer will do)
Now suppose that you said that you wanted a maximum of 60FPS on your application. Then you want that the time measured be no lower than 1/60. If the time measured s lower, then you call sleep() to reach the amount of time left for a frame.
Or you can have a variable called tick, that contains the current "game time" of the application. With the same timer, you will incremented it at each main loop of your application. Then, on your drawing routines you calculate the positions based on the tick var, since it contains the current time of the application.
The big advantage of option 2 is that your application will be much easier to debug, since you can play around with the tick variable, go forward and back in time whenever you want. This is a big plus.
Rule #1. Do not make update() or loop() kind of functions rely on how often it gets called.
You can't really get your desired FPS. You could try to boost it by skipping some expensive operations or slow it down by calling sleep() kind of functions. However, even with those techniques, FPS will be almost always different from the exact FPS you want.
The common way to deal with this problem is using elapsed time from previous update. For example,
// Bad
void enemy::update()
{
position.x += 10; // this enemy moving speed is totally up to FPS and you can't control it.
}
// Good
void enemy::update(elapsedTime)
{
position.x += speedX * elapsedTime; // Now, you can control its speedX and it doesn't matter how often it gets called.
}
Is there any way to calculate how much updates should be made to reach desired frame rate, NOT system specific?
No.
There is no way to precisely calculate how many updates should be called to reach desired framerate.
However, you can measure how much time has passed since last frame, calculate current framerate according to it, compare it with desired framerate, then introduce a bit of Sleeping to reduce current framerate to the desired value. Not a precise solution, but it will work.
I found that for windows, but I would like to know if something like this exists in openGL itself. It should be some sort of timer.
OpenGL is concerned only about rendering stuff, and has nothing to do with timers. Also, using windows timers isn't a good idea. Use QueryPerformanceCounter, GetTickCount or SDL_GetTicks to measure how much time has passed, and sleep to reach desired framerate.
Or how else can I prevent FPS to drop or raise dramatically?
You prevent FPS from raising by sleeping.
As for preventing FPS from dropping...
It is insanely broad topic. Let's see. It goes something like this: use Vertex buffer objects or display lists, profile application, do not use insanely big textures, do not use too much alpha-blending, avoid "RAW" OpenGL (glVertex3f), do not render invisible objects (even if no polygons are being drawn, processing them takes time), consider learning about BSPs or OCTrees for rendering complex scenes, in parametric surfaces and curves, do not needlessly use too many primitives (if you'll render a circle using one million polygons, nobody will notice the difference), disable vsync. In short - reduce to absolute possible minimum number of rendering calls, number of rendered polygons, number of rendered pixels, number of texels read, read every available performance documentation from NVidia, and you should get a performance boost.
You're asking the wrong question. Your monitor will only ever display at 60 fps (50 fps in Europe, or possibly 75 fps if you're a pro-gamer).
Instead you should be seeking to lock your fps at 60 or 30. There are OpenGL extensions that allow you to do that. However the extensions are not cross platform (luckily they are not video card specific or it'd get really scary).
windows: wglSwapIntervalEXT
x11 (linux): glXSwapIntervalSGI
max os x: ?
These extensions are closely tied to your monitor's v-sync. Once enabled calls to swap the OpenGL back-buffer will block until the monitor is ready for it. This is like putting a sleep in your code to enforce 60 fps (or 30, or 15, or some other number if you're not using a monitor which displays at 60 Hz). The difference it the "sleep" is always perfectly timed instead of an educated guess based on how long the last frame took.
You absolutely do wan't to throttle your frame-rate it all depends on what you got
going on in that rendering loop and what your application does. Especially with it's
Physics/Network related. Or if your doing any type of graphics processing with an out side toolkit (Cairo, QPainter, Skia, AGG, ...) unless you want out of sync results or 100% cpu usage.
This code may do the job, roughly.
static int redisplay_interval;
void timer(int) {
glutPostRedisplay();
glutTimerFunc(redisplay_interval, timer, 0);
}
void setFPS(int fps)
{
redisplay_interval = 1000 / fps;
glutTimerFunc(redisplay_interval, timer, 0);
}
Here is a similar question, with my answer and worked example
I also like deft_code's answer, and will be looking into adding what he suggests to my solution.
The crucial part of my answer is:
If you're thinking about slowing down AND speeding up frames, you have to think carefully about whether you mean rendering or animation frames in each case. In this example, render throttling for simple animations is combined with animation acceleration, for any cases when frames might be dropped in a potentially slow animation.
The example is for animation code that renders at the same speed regardless of whether benchmarking mode, or fixed FPS mode, is active. An animation triggered before the change even keeps a constant speed after the change.

Question about running a program at same speed in any computer

I made a program (in C++, using gl/glut) for study purposes where you can basically run around a screen (in first person), and it has several solids around the scene. I tried to run it on a different computer and the speed was completely different, so I searched on the subject and I'm currently doing something like this:
Idle function:
start = glutGet (GLUT_ELAPSED_TIME);
double dt = (start-end)*30/1000;
<all the movement*dt>
glutPostRedisplay ();
end = glutGet (GLUT_ELAPSED_TIME);
Display function:
<rendering for all objects>
glutSwapBuffers ();
My question is: is this the proper way to do it? The scene is being displayed after the idle function right?
I tried placing end = glutGet (GLUT_ELAPSED_TIME) before glutSwapBuffers () and didn't notice any change, but when I put it after glutSwapBuffers () it slows down alot and even stops sometimes.
EDIT: I just noticed that in the way I'm thinking, end-start should end up being the time that passed since all the drawing was done and before the movement update, as idle () would be called as soon as display () ends, so is it true that the only time that's not being accounted for here is the time the computer takes to do all of the movement? (Which should be barely nothing?)
Sorry if this is too confusing..
Thanks in advance.
I don't know what "Glut" is, but as a general rule of game development, I would never base movement speed off of how fast the computer can process the directives. That's what they did in the late 80's and that's why when you play an old game, things move at light speed.
I would set up a timer, and base all of my movements off of clear and specific timed events.
Set up a high-resolution timer (eg. QueryPerformanceCounter on Windows) and measure the time between every frame. This time, called delta-time (dt), should be used in all movement calculations, eg. every frame, set an object's position to:
obj.x += 100.0f * dt; // to move 100 units every second
Since the sum of dt should always be 1 over 1 second, the above code increments x by 100 every second, no matter what the framerate is. You should do this for all values which change over time. This way your game proceeds at the same rate on all machines (framerate independent), rather than depending on the rate the computer processes the logic (framerate dependent). This is also useful if the framerate starts to drop - the game doesn't suddenly start running in slow-motion, it keeps going at the same speed, just rendering less frequently.
I wouldn't use a timer. Things can go wrong, and events can stack up if the PC is too slow or too busy to run at the required rate. I'd let the loop run as fast as it's allowed, and each time calculate how much time has passed and put this into your movement/logic calculations.
Internally, you might actually implement small fixed-time sub-steps, because trying to make everything work right on variable time-steps is not as simple as x+=v*dt.
Try gamedev.net for stuff like this. lots of articles and a busy forum.
There is a perfect article about game loops that should give you all the information you need.
You have plenty of answers on how to do it the "right" way, but you're using GLUT, and GLUT sometimes sacrifices the "right" way for simplicity and maintaining platform independence. The GLUT way is to register a timer callback function with glutTimerFunc().
static void timerCallback (int value)
{
// Calculate the deltas
glutPostRedisplay(); // Have GLUT call your display function
glutTimerFunc(elapsedMilliseconds, timerCallback, value);
}
If you set elapsedMilliseconds to 40, this function will be called slightly less than 25 times a second. That slightly less will depend upon how long the computer takes to process your delta calculation code. If you keep that code simple, your animation will run the same speed on all systems, as long as each system can process the display function in less than 40 milliseconds. For more flexibility, you can adjust the frame rate at runtime with a command line option or by adding a control to your interface.
You start the timer loop by calling glutTimerFunc(elapsedMilliseconds, timerCallback, value); in your initialization process.
I'm a games programmer and have done this many times.
Most games run the AI in fixed time increments like 60hz for example. Also most are synced to the monitor refresh to avoid screen tearing so the max rate would be 60 even if the machine was really fast and could do 1000 fps. So if the machine was slow and was running at 20 fps then it would call the update ai function 3 times per render. Doing it this way solves rounding error problems with small values and also makes the AI deterministic across multiple machines since the AI update rate is decoupled from the machine speed ( necessary for online multiplayer games).
This is a very hard question.
The first thing you need to awnser yourself is, do you really want your application to really run at the same speed or just appear to run the same speed? 99% of the time you only want it to appear to run the same speed.
Now there are two problems: Speeding up you application or slowing it down.
Speeding up your application is really hard, since that requires things like dynamic LOD that adjusts to the current speed. This means LOD in everything, not only graphics.
Slowing your application down is fairly easy. You have two options sleeping or "busy waiting". It basically depends on your target frame rate for your simulation. If your simulation is way above something like 50 ms you can sleep. The problem is that when sleeping you are depended on the process scheduler and it works on average system at granularity of 10 ms.
In games busy waiting is not such a bad idea. What you do is you update your simulation and render your frame, then you use an time accumulator for the next frame. When rendering frames without simulation you then interpolate the state to get a smooth animation. A really great article on the subject can be found at http://gafferongames.com/game-physics/fix-your-timestep/.