【问题标题】:OpenGL ES 2.0 - Reducing memcopies when rendering to texturesOpenGL ES 2.0 - 渲染到纹理时减少内存副本
【发布时间】:2013-08-06 13:25:47
【问题描述】:

假设我有四个内容层:A、B、C 和 D;每一个都代表一种类型的视觉内容。

每一层都执行几个顺序渲染调用(没有来自各个层的交错渲染调用)。

此外,B 层和 D 层需要渲染到纹理才能应用视觉效果。为了减少内存占用,我只使用了一个只有一个纹理的 FBO。

所以,我现在这样做:

  • 渲染A内容;
  • 绑定 FBO > 渲染 B 内容 > 取消绑定 FBO > 渲染纹理(B 内容);
  • 渲染 C;
  • 绑定 FBO > 渲染 D 内容 > 取消绑定 FBO > 渲染纹理(D 内容)。

我对这种方法的主要问题是每次绑定/取消绑定 FBO 时,默认的帧缓冲区都会保存到内存中/从内存中恢复。

我不能简单地先将图层 B 和 D 绘制到 FBO,因为我无法更改图层的渲染顺序。

有没有更好的方法来做到这一点并避免多次保存/恢复主帧缓冲区?请记住,这是一个示例,实际情况更复杂(更多层)。

【问题讨论】:

  • “每次我绑定/取消绑定 FBO 时,默认的帧缓冲区都会保存到内存/从内存中恢复。” - 你确定吗? FBO 的主要原则和优势之一不是因为根本不需要逐出/恢复默认帧缓冲区,因此不会发生这种情况(但可能是 ES 硬件在这方面的行为不同,这将不过,让 FBO 在那里相当痛苦)?
  • 我不确定这是否发生在每个芯片上,但根据 Adreno 200 性能提示,每次绑定和取消绑定 FBO 时,驱动程序都会解析 GMEM 进出主内存。

标签: performance opengl-es rendering opengl-es-2.0 fbo


【解决方案1】:

能够在渲染目标之间快速切换是 FBO 功能的主要原始目的。它通常比旧的 pbuffer 方法更快,因为它不必处理不断变化的渲染上下文。此外,FBO 不像 pbuffers 那样依赖 EGL 来分配渲染表面。如果 Adreno 200 不能快速切换 FBO,那就是 Adreno 特有的实现问题。

【讨论】:

    【解决方案2】:

    驱动程序会将 FBO 的内容从内存中取回(这是一个代价高昂的操作),除非您在绘制之前使用glClear() 清除 FBO。清除 FBO 将提示驱动程序丢弃当前内容,而不是将它们从主存储器中取出。如果您的 FBO 有深度缓冲区,请确保在调用 glClear() 时也包含该位。

    由于您只使用一个 FBO,您可能无法绕过它。检查您的内存要求是否如此严格以至于不能使用第二个 FBO,因此您可以将 B 渲染到第一个 FBO,然后将 D 渲染到第二个,然后将所有内容层一起渲染到屏幕上。

    【讨论】:

    • 问题是我需要两个以上的 FBO,因为实际情况比我在问题中使用的示例更复杂。
    • 没有更多细节很难说,但也许你可以改变你的渲染调用来组合效果?比如你有A、B、C需要渲染到纹理,你可以渲染A和B,然后切换到屏幕FBO并渲染两者,然后渲染到C,带回屏幕FBO并渲染结果在 C 中。不是一个完美的解决方案,但会节省一些帧缓冲区负载。
    猜你喜欢
    • 2012-01-16
    • 1970-01-01
    • 2014-10-28
    • 2016-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多