我正在使用 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
没有必要。如果他们使用更多,那么程序将努力跟上显示帧速率,并且引入延迟会造成伤害。
现在从另一个问题的回答中得知,缓冲区交换和回溯同步在执行时不会发生SDL_GL_SwapWindow
,但这只会将“同步和交换”指令放入 OpenGL 队列,并且这条指令当之前的一切都完成时被执行。对于<some OpenGL commands>
. 但是这个指令队列是有限的,因此在某些时候我的程序不是等待回溯,而是等待指令队列中有空间。最终效果应该是相同的:如果我的事件循环的一次执行平均需要少于 16 毫秒,那么程序将平均延迟足够长的时间,以使其每次循环执行 16 毫秒。再说一遍,为什么需要显式延迟?
作为第二个问题:考虑到延迟可能会损害帧率,有没有更好的方法让 CPU 休息?