【问题标题】:Understanding the replica island rendering system. Why does it have a double-buffer of render commands?了解副本岛渲染系统。为什么它有渲染命令的双缓冲区?
【发布时间】:2017-05-29 09:58:12
【问题描述】:

我制作了一个相对简单的结构化 Android 游戏,它可以很容易地在 GLSurfaceView 的渲染线程中的 onDrawFrame 函数中更新游戏逻辑和进行渲染。但是,考虑到未来的项目,我已经开始探索多线程选项,包括在渲染线程之外运行主游戏更新逻辑,这就是副本岛所做的。这里有一篇关于它的博文:http://replicaisland.blogspot.co.nz/2009/10/rendering-with-two-threads.html

副本岛源代码 (https://code.google.com/archive/p/replicaisland/source) 等资源有助于理解这种双缓冲渲染-命令-注册多线程渲染器的想法。游戏循环更新对象,并且那些想要被绘制的对象在当前未使用的缓冲区中注册。该缓冲区在某个时候被交换,渲染器处理这些渲染命令以使用 opengl 绘制它们。

有些事情我还没有真正理解。

副本岛游戏线程循环(GameThread.java)以等待渲染器停止渲染的块开始(mRenderer.waitDrawingComplete)。然后它更新游戏逻辑,然后交换缓冲区。交换缓冲区通知渲染器开始下一批。渲染器完成后,游戏循环将再次更新,依此类推。 这种方法似乎没有运行游戏逻辑和并行循环渲染对象的代码?它们似乎步调一致地运行,并且在 onDrawFrame 函数完成后 opengl 实际完成渲染时,游戏逻辑不必阻塞,从而获得性能提升。

我测试了类似的代码,当需要绘制大量内容时,这绝对比单线程更快。但是,由于渲染循环不会在游戏线程也在处理对象时循环对象,因此似乎没有任何内在需要拥有多个渲染命令缓冲区。据我所知(我猜我在某处弄错了)游戏更新实际上并没有在渲染器使用第一个缓冲区时更新第二个缓冲区。如果是这样,那为什么还要有两个缓冲区呢?

为什么游戏线程在更新之前要等待渲染器停止绘制?

【问题讨论】:

    标签: java android multithreading opengl-es renderer


    【解决方案1】:

    毁灭战士 3 做同样的事情:处理所有应用程序输入和事件,然后kick off a separate thread 运行并绘制下一帧,同时将前一帧提交给渲染系统。然后,它在交换缓冲区之前等待Game Thread to return

    两个线程都设计为使用特定的缓冲区帧,renderdraw 帧。因为它们仅限于特定缓冲区您不需要使用互斥锁或同步原语来控制访问。等待线程同步。

    它还使渲染和绘图保持同步。您已经在后面渲染一帧,并且希望将延迟保持在最低限度。仅提前绘制一个帧意味着您的插值代码更接近经过的时间,并且每个渲染帧只需要发出一次渲染命令。 (与不断爆出帧并让渲染线程丢弃/跳过相反)。

    为什么游戏线程在更新之前要等待渲染器停止绘制?

    渲染系统是一个状态机,您不能同时对其执行命令。 Draw 发出可以在另一个线程上异步执行的渲染命令。绘制发送它们并忘记。它不关心国家或发生在他们身上的事情。这是异步的。

    将窗口模式从全屏切换到窗口、更改表面分辨率或通常任何其他渲染状态更新都需要在继续(同步或阻塞)之前完全执行,并且必须使用已知的 API 状态执行。这些和其他更新可能会影响绘图状态、窗口状态等......

    因此,明智的做法是在单个同步线程上执行事件处理和 update(),这样我们就可以在需要时阻塞并更改任何影响状态的内容(任何状态)。然后拆分并在draw线程上发出渲染命令,并在render线程上执行之前的设置。

    【讨论】:

    • 这个 quake3 引擎的故障描述了我认为的过程:fabiensanglard.net/quake3/renderer.php,这是有道理的。然而,副本岛游戏线程在其循环开始时阻塞 - github.com/jimulabs/replica-island-gradle/blob/master/app/src/… 以及交换缓冲区时。为什么两者兼而有之?这不是防止它在渲染器使用第一个缓冲区时填充第二个缓冲区吗?
    • 他交换缓冲区时的第二次阻塞还有另一个效果:它开始渲染下一帧。如果没有第一个wait,您将没有游戏循环的任何部分,您可以安全地对渲染器进行修改。为什么一开始?循环是连续的,他本可以把它放在最后。也许它只是更好地划分了非线程部分。
    • 这不是说replica island不能有效利用2-buffer系统吗? quake3 故障显示第一个缓冲区被填满,而渲染线程仍在处理第二个缓冲区并向 GPU 发送数据,但这在副本岛代码中不会发生吗?由于第一次等待,游戏线程将永远不会开始填充缓冲区,直到渲染器不再忙,这似乎破坏了 2 缓冲区系统的意义?还是我失明了,在这里遗漏了一些明显的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-19
    • 2016-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多