Why is a simple glfw program powered by an available processor, even if the progam is idle (according to the process explorer)?

I have a very simple game loop using GLFW as follows (Windows x64 Release mode)

I would expect the program to run very fast, but it seems that my delta, as calculated below, is always 16.667 ms, which would seem that glfw somehow limits the speed of my main loop. This is not a problem, since I do not care about getting more than 60 Hz. However, the process manager and the Windows task manager report that my program uses most of the processor core.

In particular, it seems that glfwSwapBuffers () eats a lot of processor, although I am not drawing anything. Removing this call reduces processor utilization by up to 0.5%.

By the way, my sleep function is almost never called, because the delta is always close to 16.6 ms.

main () { double prevTime = glfwGetTime(); //init glfw .. while(!glfwWindowShouldClose(window)) { double time0=glfwGetTime(); double delta = time0- prevTime; if (delta >= g_FrameInterval) { glfwPollEvents(); prevTime= time0; glfwSwapBuffers(window); } else { Sleep(10); } } } 
+5
source share
2 answers

glfwSwapBuffers waiting for the vsync monitor. This is why your loop operates at 60 Hz (this is the refresh rate of your monitor). As for the high processor, the OS will most likely not make your process sleep. This will probably lead to skipping vsync because it cannot wake up quickly. Instead, the CPU is placed in a busy cycle before vsync. Here is a more complete explanation of the problem.

+3
source

It seems you need to synchronize the stream based on the return of the paging buffers. Make a couple of calls to the "dummy" wap buffer (with a start screen) by reading the timer after each call to get the frequency (it may be 120 Hz on some monitors, or if the old CRT monitor, 60 Hz, 75 Hz, 85 Hz, 100 Hz, 120 Hz, 160 Hz, 200 Hz) and set the initial timer counter.

If it’s normal to work at monitor speed, you can use a fixed value of Sleep (), assuming some maximum overhead for your code (depending on the slowest possible target system). The default tick speed for Windows is 64hz (15.625 ms), but this can be accelerated using timeBeginPeriod (1), in which case Sleep (n) takes about n ms in Windows 7 or later, but up to n + 1 ms on Windows XP. For example, if your code needs less than 5 ms of processor time for each frame, then at 60 Hz you can simply use fixed Sleep (10) (or Sleep (9) if Windows XP) after each call to the swap buffers, or if at 120hz, then Sleep (2) (or Sleep (1) if Windows XP).

Many games use a separate stream for physics, which operates at a fixed frequency, not related to the frequency of the video. Here is an example of this without any drifting over time (the delta is based on the initial reading of a high-frequency clock). It will be in a separate stream from the graphic stream and will signal the graphic stream whenever the frame update is ready (mutex, semaphore, some messaging function).

 /* code for a thread to run at fixed frequency */ typedef unsigned long long UI64; /* unsigned 64 bit int */ #define FREQ 400 /* frequency */ LARGE_INTEGER liPerfTemp; /* used for query */ UI64 uFreq = FREQ; /* process frequency */ UI64 uOrig; /* original tick */ UI64 uWait; /* tick rate / freq */ UI64 uRem = 0; /* tick rate % freq */ UI64 uPrev; /* previous tick based on original tick */ UI64 uDelta; /* current tick - previous */ UI64 u2ms; /* 2ms of ticks */ UI64 i; /* ... */ /* wait for some event to start thread */ timeBeginPeriod(1); /* set period to 1ms */ Sleep(128); /* wait for it to stabilize */ u2ms = ((UI64)(liPerfFreq.QuadPart)+499) / ((UI64)500); QueryPerformanceCounter((PLARGE_INTEGER)&liPerfTemp); uOrig = uPrev = liPerfTemp.QuadPart; for(i = 0; i < (uFreq*30); i++){ /* update uWait and uRem based on uRem */ uWait = ((UI64)(liPerfFreq.QuadPart) + uRem) / uFreq; uRem = ((UI64)(liPerfFreq.QuadPart) + uRem) % uFreq; /* wait for uWait ticks */ while(1){ QueryPerformanceCounter((PLARGE_INTEGER)&liPerfTemp); uDelta = (UI64)(liPerfTemp.QuadPart - uPrev); if(uDelta >= uWait) break; if((uWait - uDelta) > u2ms) Sleep(1); } if(uDelta >= (uWait*2)) dwLateStep += 1; uPrev += uWait; /* fixed frequency code goes here */ /* along with some type of break when done */ } timeEndPeriod(1); /* restore period */ 
+2
source

Source: https://habr.com/ru/post/1202993/


All Articles