Sign in to follow this  
jamesleighe

Tracking Time

Recommended Posts

[font="Arial"](Win32, DirectX, C++)

Q1)
I use [/font][size="2"][font="Arial"]QueryPerformanceCounter to sample the current cycle count every frame, and take the difference of that and last frames cycle count to calculate the time delta of the current frame.[/font][/size][font="Arial"]

[/font][size="2"][font="Arial"]Ok, but the issue is that eventually the number returned by [/font][/size][size="2"][font="Arial"]QueryPerformanceCounter will loop back around to zero and mess stuff up...[/font][/size][font="Arial"]

[/font] [size="2"][font="Arial"]I'm guessing I just need to have a check that detects such things and prevent it from going through. Is this what I should do?[/font][/size][font="Arial"]

[/font][size="2"][font="Arial"]Q2)[/font][/size][font="Arial"]
[/font][size="2"][font="Arial"]I need to timestamp some things for various reasons and I figure the best way is to timestamp them with the time since the game started...[/font][/size][font="Arial"]

[/font] [size="3"][size="2"][font="Arial"]This would involve keeping the cycle count of the first frame around and subtracting the cycle count of the current frame to calculate the 'time'.[/font][/size][font="Arial"] [/font][/size][size="3"][size="2"][font="Arial"]Is this how you guys would track time?[/font][/size][/size][font="Arial"]

[/font] [size="3"][size="2"][font="Arial"]Thanks as usual![/font][/size][/size]

Share this post


Link to post
Share on other sites
This is how I usually calculate my frame time (i get back a result in seconds):

Init step:


LARGE_INTEGER startFrameTime;
LARGE_INTEGER endFrameTime;
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);

In main loop:

QueryPerformanceCounter(&startFrameTime);

...frame stuff...

QueryPerformanceCounter(&endFrameTime);

// calculate frame time
LONGLONG timeDiff = endFrameTime.QuadPart - startFrameTime.QuadPart;
frameTime = (float)timeDiff / (float)frequency.QuadPart;

Share this post


Link to post
Share on other sites
I do the same thing (exept I use the inverse of frequency so I can multiply)...

But my questions were:
What to do when the results loop back around?
How do you track some kind of absolute time that you can use as a timestamp? (with similar ussues with looping back around)

Share this post


Link to post
Share on other sites
If you get an endFrameTime that is less than a startFrameTime, I think you could calculate the timeDiff by:

[max LARGE_INTEGER value] - startFrameTime + endFrameTime

Share this post


Link to post
Share on other sites
[quote name='gsamour' timestamp='1310407522' post='4833876']
If you get an endFrameTime that is less than a startFrameTime, I think you could calculate the timeDiff by:

[max LARGE_INTEGER value] - startFrameTime + endFrameTime
[/quote]

Derp of cource!

EDIT: But, when tracking absolute time (time since the game started) the issue becomes more complicated. Also, even the floats will overflow eventually.
Not much of a problem for a client, since they may never play that long, but a server it will be serious.

Share this post


Link to post
Share on other sites
If the problem is serious enough (running a server for years?) then you could always increment something when you roll over. Also, you don't need to store the ticks, you can convert the delta time to milliseconds before doing an offset, so that you get plenty of playing time.

Share this post


Link to post
Share on other sites
[quote name='whiterook6' timestamp='1310410698' post='4833905']Also, you don't need to store the ticks, you can convert the delta time to milliseconds before doing an offset, so that you get plenty of playing time.
[/quote]

Could you please elaborate on what you mean here?

EDIT: I'm not sure what you mean by offset pretty much. Also, if you mean add the delta to the absolute time instead of storing the first cycle count, I COULD do that but it would get really inaccurate as the number I was adding somthing small to got larger.

Share this post


Link to post
Share on other sites
[quote name='jamesleighe' timestamp='1310406722' post='4833867'][font="Arial"]Q1) I use [/font][size="2"][font="Arial"]QueryPerformanceCounter to sample the current cycle count every frame, and take the difference of that and last frames cycle count to calculate the time delta of the current frame.[/font][/size] [size="2"][font="Arial"]Ok, but the issue is that eventually the number returned by [/font][/size][size="2"][font="Arial"]QueryPerformanceCounter will loop back around to zero and mess stuff up...[/font][/size] [size="2"][font="Arial"]I'm guessing I just need to have a check that detects such things and prevent it from going through. Is this what I should do?[/font][/size][/quote]
Without having seen your code I can almost guarantee that you are accidentally only using the lower part of the LARGE_INTEGER passed as an argument to QueryPerformanceCounter. The thing is that on a 3 GHz computer it would take 0xFFFFFFFFFFFFFFFF / 3,000,000,000 = 6148914691 seconds = 195 years for an unsigned LARGE_INTEGER to actually loop back to zero.

[quote name='jamesleighe' timestamp='1310406722' post='4833867'][size="2"][font="Arial"]Q2)[/font][/size] [size="2"][font="Arial"]I need to timestamp some things for various reasons and I figure the best way is to timestamp them with the time since the game started...[/font][/size] [size="3"][size="2"][font="Arial"]This would involve keeping the cycle count of the first frame around and subtracting the cycle count of the current frame to calculate the 'time'.[/font][/size] [/size][size="3"][size="2"][font="Arial"]Is this how you guys would track time?[/font][/size][/size] [size="3"][size="2"][font="Arial"]Thanks as usual![/font][/size][/size][/quote]
Personally I think using clock cycles to measure frame time sounds a little fanatical. Also, my own experience with performance counters is not particularly good, either, since the timer-system I wrote a while ago using them turned out to be so inaccurate it was downright useless (though this may not be the case on newer computers). Additionally, I think I once read something about these timers being even more inaccurate on laptops when these computers enter "low power mode" or something like that. My own advice would be to use timeGetTime or timeGetSystemTime since both these functions return the time since Windows started in milliseconds as a single 32-bit value (equivalent to a max session time of 1193 hours), which should be sufficiently accurate. And if you do so, be sure to call timeBeginPeriod somewhere in your program prior to using them with the smallest acceptable value (use timeGetDevCaps to find this) to ensure they are as precise as possible. Also remember to add winmm.lib to your library list when you link.

Share this post


Link to post
Share on other sites
Just to clarify I don't use the cycles AS the frametime:

[code]
Sample_ ();
time_ = double(firstCycleCount_.QuadPart - lastCycleCount_.QuadPart) * invTicksPerSecond_;
timeDelta_ = double(currentCycleCount_.QuadPart - lastCycleCount_.QuadPart) * invTicksPerSecond_;
[/code]

But it looks like all my questions have been answered, thanks guys.

FAKEDIT: I didn't realize it would take so long for a processor to loop back on an int64! Those things are monsters!
I would have to be tremendously unlucky to actually get caught in a loop-back so I'm not gona even bother coding for it.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this