转换反馈:将多个反馈批量合并在一起

时间:2017-05-10 15:02:51

标签: opengl-es transform-feedback

目标: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();
  }

即。对于每个Mesh,它首先使用Vertex Shader来计算一些每顶点的东西,将这些东西带回CPU,然后做出一些决定,然后再渲染Mesh。

这个有效,问题是速度。我们已经在几个基于OpenGL ES 3.0,3.1,3.2的设备上进行了测试,每个设备的故事看起来都是一样的:> glMapBufferRange()'电话会将FPS削减到大约一半!

我怀疑没有glMapBufferRange(),OpenGL可以懒得呈现' ,即如果将几个渲染一起批处理并按自己的方便进行,而如果我们调用glMapBufferRange(),它现在真的需要渲染,这可能会使它变慢(我们得到的数据量非常小,我真的不喜欢#39;认为这是问题所在。)

因此,我也想批评我的变换反馈,如下所示:

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数据的掌握一气呵成。)

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

性能问题是流水线操作 - 您基本上迫使GPU与CPU保持同步,因为glMapBufferRange()必须阻止,直到结果可用。这是非常糟糕的" - 所有GPU(尤其是移动设备中基于磁贴的GPU)依赖于驱动程序构建一个与应用程序异步运行的工作队列,从而保持压力以保持硬件繁忙。应用程序为强制同步和排空管道所做的任何操作都会导致性能下降。

这里的博客很好:

一般情况下,如果您正在回读CPU,则只有在对生成它的绘制调用进行排队后,才会将数据读回一帧或两帧。 (在GPU上消费结果并没有出现这个问题 - 这会导致管道问题。)

根据注释使用glBindBufferRange()将缓冲区偏移量绑定到变换反馈缓冲区。