我目前正在工作的多线程安全渲染系统,我想知道你的想法,如何正确更新游戏世界的下一个步骤,而前一个场景正在渲染。目前,我正在使用Java的LWJGL Opengl绑定。下面是我的游戏循环的伪代码,因为它是当前设置的(这可能只是大多数人熟悉的基本循环):
//DrawingLayers are wrappers for in game entities and has an update
//and render method
game-loop:
addInputEventsToInputStack()
removeCompletedDrawingLayers()
foreach layer in DrawingLayerQueue :
layer.update(deltaTime) //update position/color/size for entity
layer.render() //performs OpenGL calls
if(layer.isCompleted):
addToCompletedDrawingLayersList()
swapBuffers() //blocks until scene is fully rendered
goto game-loop我的问题在于swapBuffers()方法会阻塞,直到场景被呈现,这意味着我不能在此过程中执行任何更新。我对如何绕过这件事的想法是:
拥有用于更新实体状态的所有DrawingLayers的副本,并将另一个副本作为呈现线程的引用。当一个框架正在呈现时,在swapBuffers()之前启动一个线程来更新未使用的副本。
我对这种方法很谨慎,因为我相信在每个帧之前创建副本会比我想要的更多地减缓系统的速度。
我的方法有意义吗?如果没有,你们对如何做到这一点有什么建议吗?我愿意进行一次彻底的重组。
更新:基于datenwolf的建议,将我的游戏内容更改为:
//DrawingLayers are wrappers for in game entities and has an update
//and render method
//A future for the pre-processing task
Future preProcess = null
game-loop:
//Update: checks if we have a preprocessed update to wait for
//and waits for it to complete
if(preProcess != null):
preProcess.get()
preProcess = null
addInputEventsToInputStack()
removeCompletedDrawingLayers()
foreach layer in DrawingLayerQueue :
layer.render() //performs OpenGL calls
if(layer.isCompleted):
addToCompletedDrawingLayersList()
//UPDATE: the following just calls all the update methods for the layers
// in a new thread
preProcess = executorService.submit(new UpdateRunnable())
swapBuffers() //blocks until scene is fully rendered
goto game-loop到目前为止,我的表现有了很大的提高。可能有一些比赛条件的问题,我看不出来,但总的来说,我对这种改善感到满意。
发布于 2012-07-13 00:10:02
在swapBuffers()方法中,因为它会阻塞,直到呈现场景。
只有完成呈现,缓冲区交换的阻塞才是部分的。它通常也会因为等待回溯而阻塞。但是OpenGL向您保证,在任何绘图命令返回之后,可以安全地修改它访问的缓冲区,而不会损害任何挂起的呈现操作。实现需要对所有数据进行副本或复制-写入映射。
或者简单地说:修改缓冲区中的数据即可。一旦绘图调用(glDrawArrays、glDrawElements)返回,那么这样做是安全的。
https://stackoverflow.com/questions/11462321
复制相似问题