I’m having some trouble with SDL_Delay. I’m trying to limit framerate for a
little tech-demo practice thing I’m doing. Now, this works perfectly:==============
while (fps.stop() < ( 1000 / FPS ) ){ //fps.stop() being part of my timer
//wait // class it returns the enlapsed time
} //between start() and stop().
Of course, this uses up all the CPU time available and skips when anything
else happens. None of which are acceptable. So I used this instead:
==============
time = 33 - fps.stop(); //Time being Uint32
if ( time > 0 ){
SDL_Delay( time );
}
This is when it all breaks down. The delay has a very unpredictable behaviour.
It starts working just fine and with no speed variations… then the animation
just stops and none of the events respond. Clearly stuck in the delay function.
==============
time = 33 - fps.stop(); //Time being Uint32
if ( time > 0 ){
SDL_Delay( time );
}
Correct me if I’m wrong, but if time is an unsigned int (which is what Uint32 is)
then won’t 33-fps.stop() always be above zero if the frame doesn’t take exactly
33ms? So if your frame takes just slightly longer than the 33ms, you’ll be
waiting a looooong time for the next frame…
Either use a signed int or cast time to a signed quantity in your comparison
(the first method I think is far preferable!).
Something that might help to enhance your timer, too. Since you’ve got an object
as a timer module, you could also track the average frame rate, too, fairly
easily. That way, if you’ve got a couple of frames that take a long time to draw,
the delay for the next frame could be shortened a bit.
Quite right, my friend. I guess I figured that since the program was so very
simple there wouldn’t be any problems with that. Murphy’s law once again…
Making time an int certainly fixed the problem. I didn’t know I could use an
int since the SDL docs said SDL_Delay takes an Uint32. I guess the conditional
was pretty silly too given that its unsigned =/
So what is it that happens, the substraction comes back negative and the Uint32
takes on a “random” value as a result?
Quite right, my friend. I guess I figured that since the program was so very
simple there wouldn’t be any problems with that. Murphy’s law once again…
Making time an int certainly fixed the problem. I didn’t know I could use an
int since the SDL docs said SDL_Delay takes an Uint32. I guess the conditional
was pretty silly too given that its unsigned =/
So what is it that happens, the substraction comes back negative and the Uint32
takes on a “random” value as a result?
Thanks for the help bro.
An unsigned int takes a value between 0 and 2^N-1, whereas a signed int (int
is signed by default, so you don’t need the keyword) is -2^(N-1) through to
2^(N-2). Let’s say your system has 16-bit ints, that means unsigned is from 0 to
65535 (2^16 being 65536) and a signed int is -32768 to 32767.
The unsigned is purely a way of interpreting the number: the most significant bit
becomes the sign bit in a signed integer. Whenever it is 1, the number is assumed
to be negative. Whenever it is 0, the number is assumed to be positive. So, your
signed math 33-fps.stop() is working OK, but then the significance of the sign is
eliminated by assigning the result to an unsigned number. Likewise, the >
operation is perfectly valid for unsigned ints, it just is a complicated way of
asking if the value is non-zero. When you do a > on signed ints, however, the
sign bit is what is checked first: if it is set, the answer is false.
AFAIK, Uint32 is just a typedef of an unsigned int (or long? I forgot). So
if you use a signed int (or the typedefed Sint32) to store the result of
Uint32, it will be casted to a signed int. And for the result in Uint32 if
it’s a negative value, it will be the max unsigned int value minus the
negative value. So -10 signed int is equal to 4,294,967,295 - 10 =
4,294,967,285 in unsigned int. CMIIW.
CptAJ said:
Quite right, my friend. I guess I figured that since the program was so
very
simple there wouldn’t be any problems with that. Murphy’s law once
again…
Making time an int certainly fixed the problem. I didn’t know I could use
an
int since the SDL docs said SDL_Delay takes an Uint32. I guess the
conditional
was pretty silly too given that its unsigned =/
So what is it that happens, the substraction comes back negative and the
Uint32
takes on a “random” value as a result?
==============
time = 33 - fps.stop(); //Time being Uint32
if ( time > 0 ){
SDL_Delay( time );
}
Correct me if I’m wrong, but if time is an unsigned int (which is what Uint32 is)
then won’t 33-fps.stop() always be above zero if the frame doesn’t take exactly
33ms? So if your frame takes just slightly longer than the 33ms, you’ll be
waiting a looooong time for the next frame…
Either use a signed int or cast time to a signed quantity in your comparison
(the first method I think is far preferable!).
Neither of which are particularly ideal, actually, because they cause
unnecessary conversion work. Just rearrange the code:
if (fps.stop() < 33) {
SDL_Delay(33 - fps.stop());
}
Casting to signed ints not only requires extra conversion, but it also
still results in incorrect logic in many cases (albeit, not this one).
It’s a really bad habit to get into. If you don’t explicitly need a
negative value in your calculation, then it’s guaranteed that there is a
way to get what you want without using signed ints and without hitting
overflow issues.On Wed, 2007-07-18 at 03:40 +0000, Jason wrote:
Something that might help to enhance your timer, too. Since you’ve got an object
as a timer module, you could also track the average frame rate, too, fairly
easily. That way, if you’ve got a couple of frames that take a long time to draw,
the delay for the next frame could be shortened a bit.
Well, to be more efficient again, wouldn’t it be better if the result of
fps.stop() be stored in a temporary variable? Because in this one,
fps.stop() is called twice. And if this function is a big one, then
there’s a whole lot extra unnecessary processes.
Neither of which are particularly ideal, actually, because they cause
unnecessary conversion work. Just rearrange the code:
if (fps.stop() < 33) {
SDL_Delay(33 - fps.stop());
}
Casting to signed ints not only requires extra conversion, but it also
still results in incorrect logic in many cases (albeit, not this one).
It’s a really bad habit to get into. If you don’t explicitly need a
negative value in your calculation, then it’s guaranteed that there is a
way to get what you want without using signed ints and without hitting
overflow issues.
…
Well, to be more efficient again, wouldn’t it be better if the result
of
fps.stop() be stored in a temporary variable? Because in this one,
fps.stop() is called twice. And if this function is a big one, then
there’s a whole lot extra unnecessary processes.
Not to mention, fps.stop() might not return the same value for the two
calls. It’s implementation might be as simple as
return startTime - SDL_GetTicks();
So this code
if (fps.stop() < 33) {
SDL_Delay(33 - fps.stop());
}
would have a potential lock. If the first call returned say, 32, then
the OS decided to do something else for 2ms so the second call returns
34. Then the delay would be very big again.
Well, to be more efficient again, wouldn’t it be better if the result of
fps.stop() be stored in a temporary variable? Because in this one,
fps.stop() is called twice. And if this function is a big one, then
there’s a whole lot extra unnecessary processes.
True enough. I assumed it was something with a body as simple as
{ return ticks; } that might be optimized away, but you’re definitely
right. If the function has side effects or returns inconsistent results
between consecutive calls, a temp value is pretty vital.On Thu, 2007-07-19 at 10:07 +0700, benang at cs.its.ac.id wrote:
Neither of which are particularly ideal, actually, because they cause
unnecessary conversion work. Just rearrange the code:
if (fps.stop() < 33) {
SDL_Delay(33 - fps.stop());
}
Casting to signed ints not only requires extra conversion, but it also
still results in incorrect logic in many cases (albeit, not this one).
It’s a really bad habit to get into. If you don’t explicitly need a
negative value in your calculation, then it’s guaranteed that there is a
way to get what you want without using signed ints and without hitting
overflow issues.
…