1

目标:OpenGL ES >= 3.0。

这是我的应用程序的作用:

generateSeveralMeshes()
setupStuff();

for (each Mesh)
  {
  glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, myBuf);
  glBeginTransformFeedback( GLES30.GL_POINTS);
  callOpenGLToGetTransformFeedback();
  glMapBufferRange(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, ...)   // THE PROBLEM
  computeStuffDependantOnVertexAttribsGottenBack();
  glUnmapBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER);
  glEndTransformFeedback();
  glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);

  renderTheMeshAsNormal();
  }

即,对于每个网格,它首先使用顶点着色器计算一些每个顶点的东西,将这些东西返回给 CPU,基于此做出一些决定,然后才渲染网格。

这行得通,问题是速度。我们已经在几个基于 OpenGL ES 3.0、3.1、3.2 的设备上进行了测试,在每一个设备上,情况看起来都一样:“glMapBufferRange()”调用将 FPS 降低了大约一半!

我怀疑如果没有 glMapBufferRange(),OpenGL 可以“延迟”渲染,即将多个渲染一起批处理并在自己方便的时候进行,而如果我们调用 glMapBufferRange(),它现在确实需要渲染,这可能会使其变慢(我们得到的数据量很小,我真的不认为这是问题)。

因此,我也想批量处理我的转换反馈,如下所示:

generateSeveralMeshes()
setupStuff();

for (each Mesh)
  {
  glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, myLargerBuf);
  glBeginTransformFeedback( GLES30.GL_POINTS);
  setupOpenGLtoSaveTransformFeedbackToSpecificOffset();
  callOpenGLToGetTransformFeedback();
  advanceOffset();
  glEndTransformFeedback();
  glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);

  renderTheMeshAsNormal();
  }

glMapBufferRange(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, ...)
computeStuffDependantOnVertexAttribsGottenBackInOneBatch();
glUnmapBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER);

问题是我不知道如何告诉 OpenGL 不将变换反馈输出保存到开头,而是保存到 TRANSFORM_FEEDBACK_BUFFER 中的特定偏移量(这样我可以稍后在循环之后,将手放在所有 TF数据一次返回)。

有什么建议吗?

4

1 回答 1

1

性能问题是流水线——你基本上是在迫使 GPU 与 CPU 同步,因为glMapBufferRange()在结果可用之前必须阻塞。这是“非常糟糕的”——所有 GPU(尤其是移动设备中基于 tile 的 GPU)都依赖于驱动程序建立一个与应用程序异步运行的工作队列,从而保持前向压力以保持硬件忙碌。应用程序为强制同步和耗尽管道所做的任何事情都会降低性能。

好的博客在这里:

通常,如果您在 CPU 上回读数据,则仅在将生成数据的绘制调用排队后将数据读回一到两帧。(在 GPU 上使用结果没有这个问题 - 这将流水线)。

要将缓冲区偏移量绑定到变换反馈缓冲区中,请按照注释使用glBindBufferRange().

于 2017-05-11T08:36:00.690 回答