exotic performance questions

Started by
11 comments, last by MrSandman666 22 years, 5 months ago
Hello again! After a long period of inactivity I''ve finally returned to OpenGL programming. When I stopped programming last time I was using my old computer and was happy when I got framerate beyond 30. Now I have this new computer (P4 1.8 GHz, 512MB RAM, GeForce3 Ti 200 64MB) and I was compiling an old project of mine, using the same framerate counter I used before. First I had VSync on, so that I never got more than about 80 FPS, due to my monitor. Now I switched VSync of and the frame rate counter doesn''t work anymore. Most of the time it only displays total garbage. Is my computer too fast to compute frame rates accurately? I don''t think so. This is my framerate counter: enTime = ((float)timeGetTime() - LastTime) / 1000.0f; enFps = 1.0f/enTime; LastTime = (float)timeGetTime(); I then use a function similar to the DOS function printf() to display the frame rate. I actually used the one from NeHe''s font tutorials (which uses vsprintf()), so you can look it up there. I feed it something like ("fps: %5.2f", enFps) and it works perfectly as long as I have VSync enabled, giving me a steady framerate between 66 and 80. But as soon as I turn VSync off, All I get is garbage. Something like "fps: 1.#INF00" Any idea what that could mean? And my other questions is: What is faster: triangle strips or seperate triangles? So, if I have to display a few thousand (textured) quads, would it be faster to use a small triangle strip for every one or to build every quad out of 2 triangles? Thanks in advance. ----------------------------- "Mr Sandman bring me a dream"
-----------------------------"Mr Sandman bring me a dream"
Advertisement
Your computer is too fast for an accurate time. It is most likely due to the granularity of your timer rather than you processor being too fast. That being said you machine is very fast so for small scenes you can run too fast to get a time. #INF probably stands for infinite or undefined since you are dividing 0 by 1000.0f.

The fanatic is incorruptible: if he kills for an idea, he can just as well get himself killed for one; in either case, tyrant or martyr, he is a monster.
--EM Cioran

Opere Citato
You are seeing garbage because your timer is not precise enough.


You are using a millisecond timer so the smallest value it can resolve is a difference of 0.001. Well that means if you get more than a 1000 fps(which is very likely with your machine) than the frametime will give you 0.


And what happens if you divide float point number by 0? you get 1.#INF00.!! It is an exception.

So you have 2 solutions to your problem :

1. Make your project more visually intense so that you get less than a thousand fps. (This means that in a couple of years, you will probably get a new machine that will again blow the 1000 fps).

2. Use a more precise timer! Under Windows, look into QueryPerformanceTimer. This is precise to a nanoseconds. There is no way you will blow this one up for a while. Other platform(unix,linux, macos) also provide high accuracy timer. If you need them you can find code on the web.


For your 2nd question.

1.If you are drawing a quad at a time, than Quad is as fast as strip and they are both faster than a triangle, because you only pass 4 vertices whereas for a triangle you pass 7.

2. If you are using vertex arrays, then triangle strips will be faster.
Hey, thank you!

I''ll definately look into the QueryPerformanceTimer. I found something about a QueryPerformanceCounter is that what you mean?
I''ll try that.

Ok, so thanks a lot!



-----------------------------
"Mr Sandman bring me a dream"
-----------------------------"Mr Sandman bring me a dream"
DAMN!!!
QueryPerformanceCounter uses LARGE_INTEGER as a return type. Bad thing is just that this datatype doesn''t accept any standard operators like plus or minus and that it can''t be converted to int or float.

Are there any other high performance timers for windows out there?

-----------------------------
"Mr Sandman bring me a dream"
-----------------------------"Mr Sandman bring me a dream"
Good news! Firstly, your computer is not too fast for this timer to work. Secondly, it is only a minor code change to fix your problem. I did a test just to make sure with the fastest, most simple code that I could and my counter code correctly measured to over 15000 fps.

Also, there is pretty much a 0% chance that any current computer will get over 1000 fps or even 500fps for that matter, considering flipping buffers usually takes that much time.

That aside however, your counter doesn't work because of the way you cast things to float. To maintain enough accuracy, some things must be maintained, like the full millisecond value. The only way to do this using calculations like you have is annoying, somewhat inaccurate and slow. Instead, it is easier just to count frames. For your convenience and anyone else's who needs counter code, here is a really simple object that I programmed that works perfectly and easily:

The header file looks like this:

    //---------------------------------------------------------------------------#ifndef TFPSCounterH#define TFPSCounterH//---------------------------------------------------------------------------// A nice class that records and updates a frames per second count every second.// Call the DoFrame method every frame to update the count, and call GetFPS to// read the most current fps.class TFPSCounter{private:    DWORD LastFPSTime;    DWORD CurrentTime;    int LastFPS;    int FramesSoFar;public:    TFPSCounter ();    void DoFrame ();        int GetFPS ()    {   return LastFPS; }};//---------------------------------------------------------------------------#endif  


And the source file is even simpler, being the following:

        //---------------------------------------------------------------------------#include <windows.h>#include "TFPSCounter.h"//---------------------------------------------------------------------------TFPSCounter::TFPSCounter (){    // Do any initializations    LastFPS = 0;    LastFPSTime = GetTickCount ();    FramesSoFar = 0;}//---------------------------------------------------------------------------void TFPSCounter::DoFrame (){    // We've done a frame, so save that    FramesSoFar ++;    CurrentTime = GetTickCount ();    if (CurrentTime - LastFPSTime >= 1000)      // More than one second has passed    {        // We need to update our last fps        LastFPS = FramesSoFar;        FramesSoFar = 0;        LastFPSTime = CurrentTime;    }}//---------------------------------------------------------------------------  


That code should work perfectly, no matter how fast your computer gets. Just use the object as follows:

              // Game Init:TFPSCounter *FPSCounter = new TFPSCounter;...// Game Frame Code:while (!Exit){    ... // All game stuff here    FPSCounter->DoFrame ();    // Draw the FPS to the screen (however you do it)    DrawFPS (FPSCounter->GetFPS ());}...// Game Cleanupif (FPSCounter){    delete FPSCounter;    FPSCounter = NULL;}  


There you are. Start to finish. I hope that works great for you and good luck with your future programming!

PS: Sorry for how the MB messed up the source slightly... I'm sure you can add the appropriate line feeds after the defines and includes (before the //-----...'s).

Edited by - AndyTX on December 2, 2001 2:11:53 PM
Yup! Works great! Thank you for that one.
I like it. I "personalized" it a little and might modify it a little more.
This little peace of code gave me the precious insight that my computer calculates the scene with about 400 fps.

-----------------------------
"Mr Sandman bring me a dream"
-----------------------------"Mr Sandman bring me a dream"
Good, I am glad that it was helpful. Feel free to "personalize", distribute or do whatever you wish with it. If you improve it a lot make sure to re-post it here so that I can steal it back

Happy coding.
Ok, the first thing I did is trade a little accuracy for speed.
your version has the disadvantage of refreshing only once every second, and I find a second to be a very long time.

I changed a little bit of the code so it refreshes more often (ten times each second):

  Frames++;if (CurrentTime - LastFrameTime >= 100){   enFps = Frames*10;   Frames = 0;   LastFrameTime = CurrentTime;}  


Of course these FPS numbers are only approximated, but after all, that''s what fps is, right? An approximated, average value of the number of frames per second.

I also found out that my computer renders an empty scene (just the text for time and fps) at about 2500 fps. I know it''s stupid but it makes me feel good.

-----------------------------
"Mr Sandman bring me a dream"
-----------------------------"Mr Sandman bring me a dream"
With using LARGE_INTEGER and QueryPerformanceFrequency / QueryPerformanceCounter, access the data within the LARGE_INTEGER like so:

LARGE_INTEGER count;
QueryPerformanceCounter(&tmp_time);
printf("%5.2f", (float)count.QuadPart);

LARGE_INTEGER.QuadPart gives you access to the data, which you can perform mathematical operations or whatever on.
-----------------------"When I have a problem on an Nvidia, I assume that it is my fault. With anyone else's drivers, I assume it is their fault" - John Carmack

This topic is closed to new replies.

Advertisement