• Advertisement
Sign in to follow this  

QueryPerformanceCounter Questions

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

I used to use timeGetTime() but its low resolution was cuasing me some problems. Now im trying to use query performance counter but im running into new problems. Maybe an extra set of eyes can help me spot them. The problem: The programs output is it count of FPS and the frame time. The numbers dont coincide with eachother. I just cant figure out why. Here is the relevant code, I really cant see whats worng even though its probably something simple I've been staring at it for an hour!
    //fps stuff
    //start and end_time are used to get the time it takes for one frame.
    LARGE_INTEGER timetmp;
    
    __int64 start_time = 0, end_time = 0;
    long frame_count = 0;
    //sec_e is used to see if a second has passed.
    __int64 sec_e = 0;
    
    __int64 second;
    
    QueryPerformanceFrequency(&timetmp);
    second = timetmp.QuadPart;

    while((msg.message!=WM_QUIT))
    {
        QueryPerformanceCounter(&timetmp);     //Begin timing frame
        start_time = timetmp.QuadPart;

        //Do my thing... draw a frame. None of the timing related variable get touched here.


        //Advance the frame counter
        frame_count++;
        //And see if a second has elapsed
        if(start_time - sec_e > second)
        {
            // Its been a second so put the number of frames rendered into g_fps and clear the frame counter
            g_fps = frame_count;
            frame_count = 0;
            
            //Start timing a second again
            QueryPerformanceCounter(&timetmp);
            sec_e = timetmp.QuadPart; 
            
            //TODO:
            if(1) //If fps is being displayed
            {
                //Display g_fps somewhere
                char ss[30];
                statstr = "";
                sprintf(ss, "FPS: %d FrameTime: %f ms", g_fps, (float)( start_time - end_time));
                AddListText(ss);
            }    
        }
        QueryPerformanceCounter(&timetmp); //set the frame end time
        end_time = timetmp.QuadPart;
     }



[Edited by - chad_420 on June 1, 2005 3:03:18 AM]

Share this post


Link to post
Share on other sites
Advertisement
It probably ought to be (end_time - start_time) in the sprintf and then you need to snap end_time prior to the fps code block. Right now I think you're timing the loop overhead.

Share this post


Link to post
Share on other sites
(end_time - start_time) give me negative numbers... and no I really dont get it either :D but the case is the same for timeGetTime();

edit: you make sense now too lol!

[Edited by - chad_420 on June 1, 2005 3:53:02 AM]

Share this post


Link to post
Share on other sites
QueryPerformanceCounter() does not return the number of milliseconds, it returns the number of "ticks" elapsed.

What you need to do is divide the number of ticks by the value you recieved from QueryPerformanceFrequency() to determine the number of elapsed seconds, and then multiply that by 1000 to convert to milliseconds.

I took your code and converted it into a simple console application, and simulated frame rendering time with Sleep(rand()%10).
I also added code so that the displayed FrameTime is an average of all the frames within that second, instead of the most recent at the time of fps printing.

Here's the output:
FPS: 192 Avg FrameTime: 5.2191 ms
FPS: 177 Avg FrameTime: 5.6576 ms
FPS: 205 Avg FrameTime: 4.8857 ms
FPS: 200 Avg FrameTime: 5.0177 ms
FPS: 188 Avg FrameTime: 5.3483 ms
FPS: 182 Avg FrameTime: 5.5193 ms


And here's the source:
//fps stuff
//start and end_time are used to get the time it takes for one frame.
LARGE_INTEGER timetmp;

__int64 start_time = 0, end_time = 0, frame_time_avg=0;
long frame_count = 0;
long g_fps=0;
__int64 second;
__int64 sec_e=0;

QueryPerformanceFrequency(&timetmp);
second = timetmp.QuadPart;

// get start time BEFORE we enter the loop.
QueryPerformanceCounter(&timetmp);
sec_e = timetmp.QuadPart;

while(true)
{
//start frame timing
QueryPerformanceCounter(&timetmp);
start_time = timetmp.QuadPart;

//Do my thing... draw a frame. None of the timing related variable get touched here.
// simulate a frame
Sleep(rand()%10);


//Advance the frame counter
frame_count++;

// stop frame timing
QueryPerformanceCounter(&timetmp); //set the frame end time
end_time = timetmp.QuadPart;

// accumulate frame times for the average.
frame_time_avg += (end_time-start_time);

//And see if a second has elapsed
if(end_time - sec_e >= second)
{
// Its been a second so put the number of frames rendered into g_fps and clear the frame counter
g_fps = frame_count;
frame_count = 0;


//TODO:
if(1) //If fps is being displayed
{
//Display g_fps somewhere
double dAvgFrameTicks = double(frame_time_avg)/g_fps;

double dElapsedMs = (dAvgFrameTicks/second)*1000;
printf("FPS: %d Avg FrameTime: %0.4f ms\r\n", g_fps, dElapsedMs);
}
frame_time_avg = 0;

QueryPerformanceCounter(&timetmp);
sec_e = timetmp.QuadPart;

}

}




[Edited by - pragma Fury on June 1, 2005 2:55:51 AM]

Share this post


Link to post
Share on other sites
Thanks pragma, I have been crackin at this all day and still havent got there. I'm give your code a shot now. Unfortunatly I still dont understand how I got such high number for frame_count before.

Edit: Lol I see now... how foolish lol! Thanks again pragma fury

Edit2: Got the code working. Didnt think so at first frame count was 250000 with a frame time of 0.001 which doesnt really add up... But when I add sleep(5) it sit right around 5.001 ms and 200 frame so It seems all is well. Still the count is funky at over 1000fps.

[Edited by - chad_420 on June 1, 2005 3:55:33 AM]

Share this post


Link to post
Share on other sites
You should consider wrapping your timer up into a class instead of manually calling QPC...That way you can reuse it. Something like this would probably be all you need...


class CHighResTimer
{
public:
CHighResTimer()
{
::ZeroMemory(&m_start, sizeof(m_start));
::ZeroMemory(&m_stop, sizeof(m_stop));

LARGE_INTEGER tempFreq;
::QueryPerformanceFrequency(&tempFreq);

// so we don't have to cast every time we call GetSeconds...
m_freq = static_cast<double>(tempFreq.QuadPart);
}

virtual ~CHighResTimer()
{
}


public:

void StartTime()
{
::QueryPerformanceCounter(&m_start);
}

double GetSeconds()
{
::QueryPerformanceCounter(&m_stop);
return( (m_stop.QuadPart - m_start.QuadPart) / m_freq);
}

__int64 GetTicks()
{
::QueryPerformanceCounter(&m_stop);
return( m_stop.QuadPart - m_start.QuadPart );
}

private:
LARGE_INTEGER m_start;
LARGE_INTEGER m_stop;
double m_freq;

};



hth,
moe.ron

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement