【问题标题】:Syncing openGL rendering with c++ game loop on android在android上将openGL渲染与c ++游戏循环同步
【发布时间】:2014-12-25 15:00:48
【问题描述】:

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

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

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

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

步骤 2. 根据输入更新游戏对象(如果需要)

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

步骤 4. 调用 glSwapBuffers

然后循环回到步骤 1

但是我在同步和线程方面遇到了各种困惑,所以我将所有问题一起列出。

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

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

3. 由于所有调用都是异步的,我如何测量渲染每一帧所花费的时间? glSwapBuffers 会立即返回,所以我怎么知道帧实际何时完成?

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

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

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

【问题讨论】:

    标签: android c++ multithreading opengl-es


    【解决方案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 关闭)。

    【讨论】:

    • 啊,被告知的感觉真好。那么方法 1 是否适用于像应用程序这样的实时游戏?
    • @Allahjane:一般来说,是的。通常,您不需要努力同步交换缓冲区。在更新动态数据(如纹理或顶点数据流)的情况下,同步(或避免隐式同步)需要更多努力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多