Hello,
I was looking through the day18 code again and checked some of the docs regarding Sleep
and timeBeginPeriod
.
The doc for Sleep
says we must call the timeEndPeriod
at the end of the application, and vaguely threatens that not doing so will do something to the battery (I don't quite understand what its trying to say). timeEndPeriod
was not called in the lesson. So, is it important that I call it at the end?
From the doc:
Use caution when calling timeBeginPeriod, as frequent calls can significantly affect the system clock, system power usage, and the scheduler. If you call timeBeginPeriod, call it one time early in the application and be sure to call the timeEndPeriod function at the very end of the application.
So what does the timeBeginPeriod
function actually do? Does it actually set the granularity of the system clock for the whole computer, instead of just this application? And if so, what is to prevent some application from setting it to something bad and then crashing before unsetting it? Or even just not unsetting it, like the game?
Another question about variable refresh rates. I remember Casey Muratori explaining how variable refresh rates do not make sense (for gaming at least) because we need to know what the fixed refresh rate is in order to do simulation of the game. While reading the above I came across this doc: https://learn.microsoft.com/en-us/windows/win32/directcomp/compositor-clock/compositor-clock
which says that its used for latency sensitive stuff such as drawing on the screen with a pen.
And this doc has a function that lets you wait for the next frame (of the monitor)
DWORD DCompositionWaitForCompositorClock( UINT count, const HANDLE *handles, DWORD timeoutInMs );
So can we use this to get the refresh rate at the startup of the game? For example something like:
LARGE_INTEGER FrameStart; QueryPerformanceCounter(&FrameStart); DCompositionWaitForCompositorClock(1, Handle, INFINITE); LARGE_INTEGER FrameEnd; QueryPerformanceCounter(&FrameEnd); int32 RefreshRate = (FrameEnd.QuadPart - FrameStart.QuadPart)/CounterFrequency;
I can't figure out what it wants in the second argument as Handle
though.
Kernel internally has "tick" rate on which it updates specific things like sleeping/waiting threads & updating timers. This "period" thing allows to adjust this tick rate. The lower you go the more often it will wake up and allow more granular sleeps - with caveat that it will use more cpu time because it will run kernel code more often.
If you don't call EndPeriod, then kernel will automatically do that when process ends. That is not a problem.
And in newer Win10 versions this period is process local so it should not affect performance of whole system much. Just a bit. But in older Win versions it was not a nice thing to do: https://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/
Handle's for DCompositionWaitForCompositorClock are extra handles this function will wait on. In case you want to wait on compositor and something extra (like game quit event, or file i/o). The function will return when either compositor signals, or one of these handles will signal.
Newer API's like this allows to get more detailed information & more control over compositing, which should be better than sleeping to simulate "vsync". The more interesting things are described here: https://learn.microsoft.com/en-us/windows/win32/comp_swapchain/comp-swapchain-examples (examples 11,12,13) I have not tried it myself, but it should allow to wait until presentation is actually possible, without queuing up presents with large latency.
This would solve "frame pacing" problem - see excellent presentations from Croteam about it:
https://medium.com/@alen.ladavac/the-elusive-frame-timing-168f899aec92
https://www.gdcvault.com/play/1025031/Advanced-Graphics-Techniques-Tutorial-The
I know there are lots of people who don't like chrome. But as a web developer I have to use it as it has the best developer tools in my experience. So, it hurts to see chrome up there in the list of culprits. SQL server doesn't hurt as much as I don't use it. I wash my hands off of its crimes.
If you don't call EndPeriod, then kernel will automatically do that when process ends. That is not a problem.
thats good to know. No cleanup required for something that doesn't run in the background, like a game. From that article it looks like the ticker is basically running at 1ms all the time because of one application or the other and that too because of Microsoft's own programs. That is so sad.
ETW tracing and looking at the Microsoft-Windows-Kernel-Power provider shows that the OS itself is modifying the timer interrupt frequency (SystemTimeResolutionKernelChange events) about 30 times a second. I have been told that there are no power implications to kernel timer interrupt frequency changes, but even if that is true they make clockres and TimerTool useless. What a shame.
I'm beginning to see why advanced programmers are so angry at windows.
The composition API and frame pacing are completely new things to me. Thanks for showing these, I'm reading, but first I'll watch the video 😅