我正在Python中使用SDL2和OpenGL(pysdl2,PyOpenGL)编写实时交互式图形应用程序。该应用程序连续产生帧,这些帧可能会响应键盘/鼠标输入或根据时间而变化。
我的主要事件循环是从网络上一些我无法找到的模糊来源复制而来,看起来(简化)如下:
event = sdl2.SDL_Event()
running = True
while running:
# process events
while sdl2.SDL_PollEvent(ctypes.byref(event)) != 0:
if event.type == sdl2.SDL_QUIT:
running = False
# render frame
<some OpenGL commands>
sdl2.SDL_GL_SwapWindow(window)
sdl2.SDL_Delay(10)
据我了解,延迟10毫秒旨在为CPU提供一些喘息的空间,实际上,当我将其卸下时,CPU使用率将翻倍。
我不明白的是为什么有必要。图形显示是双缓冲的,并且缓冲交换与垂直回扫同步(60 Hz = 16 ms)。天真地希望,如果<some OpenGL commands>
花费的时间少于16毫秒,那么SDL_GL_SwapWindow
仍然会引入延迟,因此SDL_Delay
是不必要的。而且,如果它们使用更多的内容,则该程序将难以跟上显示帧速率的步伐,并且引入延迟会很不利。
现在,根据我在response to another question中所讲的,执行SDL_GL_SwapWindow
时不会发生缓冲区交换,因此回溯同步不会发生,但这只会引起“同步与交换”指令进入OpenGL队列,并且所有之前的内容都将完成时执行该指令。 <some OpenGL commands>
也是如此。但是此指令队列是有限的,因此在某些时候,我的程序将等待指令队列中的空间,而不是等待回溯。最终效果应该是相同的:如果事件循环的一次执行平均需要少于16毫秒,则该程序的平均延迟时间将足以使其每次循环执行16毫秒。再说一遍,为什么显式延迟是必要的?
第二个问题:考虑到延迟可能会损害帧速率,是否有更好的方法让CPU静止?