在Android上将openGL渲染与c ++游戏循环同步

时间:2014-12-25 15:00:48

标签: android c++ multithreading opengl-es

我正在使用Android NDK和openGL ES 2.0构建类似应用程序的游戏

到目前为止,我理解顶点和着色器和程序的概念。

主游戏循环将是单个线程中的循环,如下所示

步骤1.阅读所有用户输入

步骤2.根据输入

更新游戏对象(如果需要)

步骤3.对所有对象进行绘制调用

步骤4.调用glSwapBuffers

然后循环回到第1步

但是我遇到了有关同步和线程的各种混淆,所以我将所有问题列在一起。

1.由于开放GL绘制调用是异步的,因此绘制调用和glSwapBuffers可能会在gpu甚至从上一次循环迭代的调用实际呈现单个帧之前被调用多次。这会有问题吗?缓冲区溢出或撕裂?

2.假设VSYNC已启用,那么点1是否仍会导致问题?

3.由于所有呼叫都是异步的,我如何衡量渲染每帧的时间? glSwapBuffers会立即返回,所以我怎么知道帧实际上是什么时候完成的?

4.加载纹理会占用ram中的空间是在加载纹理标准方式之前检查空闲内存还是我应该继续加载纹理直到我达到OUT_OF_MEMORY_ERROR?

5.如果我切换到多线程方法,只需要每秒固定60次调用glswapbuffers,而不考虑正在处理输入并发出绘制调用的线程那么应该发生什么?

另外我如何控制游戏循环中的fps?我知道确切的fps取决于很多因素,但你怎么能接近那个

1 个答案:

答案 0 :(得分:1)

  1. SwapBuffers()不会无序执行。在帧的所有绘制命令之后发出它是好的。司机会照顾它,你不需要同步任何东西。你只能通过使用多个线程或多个上下文来解决这个问题,但即使这样也需要付出很多努力。

  2. 1没有问题,VSYNC在这里没有直接改变任何内容。

  3. 调用可能是异步的,但驱动程序不会排队数量不等的工作。如果你提前发出太多电话,它迟早会被阻止。当vsync打开时,典型的行为是驱动程序最多排队几帧(或只有一帧,具体取决于驱动程序设置),SwapBuffers() 阻止到达了。因此,在前几帧之后,您获得的时序统计数据是准确的。请注意,这仍然比完全刷新队列要好得多,因为驱动程序会在执行第一个挂起缓冲区交换后立即解除阻塞。

  4. 这是一个全新的话题,可能属于另一个问题。但是:您不太可能获得任何当前的桌面GL实现来生成GL_OUT_OF_MEMORY。驱动程序将自动在VRAM和系统RAM之间分页纹理(和其他对象)(操作系统甚至可以将其分页到磁盘)。 GL也无法查询可用内存。

  5. 在这种情况下,您需要手动同步。这种方法没有丝毫意义,似乎试图解决一个不存在的问题。如果您希望您的游戏使用多线程,仍然将所有gl渲染(和交换缓冲区)放入同一个线程中。您可以使用不同的线程进行输入处理,声音,物理,场景更新,一般游戏逻辑等等。但是你应该只为GL使用单线程/单一上下文方法。这样,当SwapBuffers()阻止你的渲染线程时,它也不会伤害你,因为你的游戏逻辑和输入处理仍然完成,并且渲染线程将只渲染具有频率中最新可用数据的新帧。显示需求(使用vsync)或者CPU和GPU可以正常工作(如果vsync关闭)。