store win32 timer start & frequency in terms of nanoseconds
This commit is contained in:
parent
4eef91dd63
commit
a20e8eced5
@ -98,8 +98,9 @@ struct win32_window {
|
||||
|
||||
GLOBAL struct {
|
||||
SYSTEM_INFO info;
|
||||
LARGE_INTEGER timer_frequency;
|
||||
LARGE_INTEGER timer_start;
|
||||
i64 timer_frequency_s;
|
||||
i64 timer_frequency_ns;
|
||||
i64 timer_start_ns;
|
||||
i32 scheduler_period_ms;
|
||||
DWORD thread_tls_index;
|
||||
u32 main_thread_id;
|
||||
@ -235,21 +236,12 @@ INTERNAL struct sys_datetime win32_time_to_sys_time(SYSTEMTIME st)
|
||||
};
|
||||
}
|
||||
|
||||
/* prevent 64-bit overflow when computing relative timestamp
|
||||
* https://github.com/floooh/sokol/blob/d4ac122f36d7659a18b312fd4fa2317fb9e06a63/sokol_time.h#L203
|
||||
*/
|
||||
INTERNAL i64 _win32_i64_muldiv(i64 value, i64 numer, i64 denom) {
|
||||
i64 q = value / denom;
|
||||
i64 r = value % denom;
|
||||
return q * numer + r * numer / denom;
|
||||
}
|
||||
|
||||
struct sys_timestamp sys_timestamp_prog(void)
|
||||
{
|
||||
struct sys_timestamp ts;
|
||||
LARGE_INTEGER time;
|
||||
QueryPerformanceCounter(&time);
|
||||
ts.v = (u64)_win32_i64_muldiv(time.QuadPart - G.timer_start.QuadPart, 1000000000, G.timer_frequency.QuadPart);
|
||||
LARGE_INTEGER qpc;
|
||||
QueryPerformanceCounter(&qpc);
|
||||
ts.v = (qpc.QuadPart * G.timer_frequency_ns) - G.timer_start_ns;
|
||||
return ts;
|
||||
}
|
||||
|
||||
@ -1951,24 +1943,24 @@ INTERNAL void win32_precise_sleep_timer(f64 seconds, HANDLE timer)
|
||||
/* TODO: Does the high frequency timer even require setting / scaling of
|
||||
* timeBeginPeriod/scheduler_period_ms? There isn't much documentation. */
|
||||
|
||||
i64 qpc_per_second = G.timer_frequency.QuadPart;
|
||||
i64 qpc_per_second = G.timer_frequency_s;
|
||||
i32 scheduler_period_ms = G.scheduler_period_ms;
|
||||
|
||||
LARGE_INTEGER qpc;
|
||||
QueryPerformanceCounter(&qpc);
|
||||
INT64 target_qpc = (INT64)(qpc.QuadPart + seconds * qpc_per_second);
|
||||
i64 target_qpc = (i64)(qpc.QuadPart + seconds * qpc_per_second);
|
||||
|
||||
/* TODO: Maybe increase tolerance for higher precision but more power usage */
|
||||
//const double tolerance = 0.001200 * scheduler_period_ms;
|
||||
const double tolerance = 0.000520 * scheduler_period_ms;
|
||||
//const double tolerance = 1 * scheduler_period_ms;
|
||||
//const f64 tolerance = 0.001200 * scheduler_period_ms;
|
||||
const f64 tolerance = 0.000520 * scheduler_period_ms;
|
||||
//const f64 tolerance = 1 * scheduler_period_ms;
|
||||
|
||||
INT64 max_ticks = (INT64)scheduler_period_ms * 9500;
|
||||
i64 max_ticks = (i64)scheduler_period_ms * 9500;
|
||||
while (true) {
|
||||
__profscope(win32_sleep_part);
|
||||
/* Break sleep up into parts that are lower than scheduler period */
|
||||
double remaining_seconds = (double)(target_qpc - qpc.QuadPart) / (double)qpc_per_second;
|
||||
INT64 sleep_ticks = (INT64)((remaining_seconds - tolerance) * 10000000);
|
||||
f64 remaining_seconds = (f64)(target_qpc - qpc.QuadPart) / (f64)qpc_per_second;
|
||||
i64 sleep_ticks = (i64)((remaining_seconds - tolerance) * 10000000);
|
||||
if (sleep_ticks <= 0) {
|
||||
break;
|
||||
}
|
||||
@ -1992,7 +1984,7 @@ INTERNAL void win32_precise_sleep_timer(f64 seconds, HANDLE timer)
|
||||
INTERNAL void win32_precise_sleep_legacy(f64 seconds)
|
||||
{
|
||||
__prof;
|
||||
i64 qpc_per_second = G.timer_frequency.QuadPart;
|
||||
i64 qpc_per_second = G.timer_frequency_s;
|
||||
i32 scheduler_period_ms = G.scheduler_period_ms;
|
||||
|
||||
LARGE_INTEGER qpc;
|
||||
@ -2080,13 +2072,18 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
||||
|
||||
/* Query system info */
|
||||
GetSystemInfo(&G.info);
|
||||
QueryPerformanceFrequency(&G.timer_frequency);
|
||||
QueryPerformanceCounter(&G.timer_start);
|
||||
{
|
||||
|
||||
LARGE_INTEGER qpf;
|
||||
QueryPerformanceFrequency(&qpf);
|
||||
G.timer_frequency_s = qpf.QuadPart;
|
||||
G.timer_frequency_ns = 1000000000 / qpf.QuadPart;
|
||||
|
||||
LARGE_INTEGER qpc;
|
||||
QueryPerformanceCounter(&qpc);
|
||||
G.timer_start_ns = qpc.QuadPart * G.timer_frequency_ns;
|
||||
|
||||
TIMECAPS caps;
|
||||
timeGetDevCaps(&caps, sizeof caps);
|
||||
G.scheduler_period_ms = (i32)caps.wPeriodMin;
|
||||
}
|
||||
timeGetDevCaps(&caps, sizeof(caps));
|
||||
|
||||
/* Set up timing period */
|
||||
timeBeginPeriod(G.scheduler_period_ms);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user