Why glBufferSubData need to wait until the VBO is not used by glDrawElements?
在OpenGL Insights中,它表示" OpenGL驱动程序必须等待,因为使用了VBO
通过glDrawElements从上一帧开始"。
这让我很困惑。
据我所知,glBufferSubData会将数据复制到临时内存中,然后在以后传输到GPU。
那么为什么驾驶员仍然需要等待呢?它可以仅将Transfer命令附加到命令队列中,从而将数据传输到GPU的时间延迟到glDrawElements完成之前,对吧?
- - - 添加 - - - - - - - - - - - - - - - - - - - - - - ------------------------------
在OpenGL Insights中,它表示:
http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf(页397)
However, when using glBufferSubData or glMapBuffer[Range], nothing in
the API itself prevents us from modifying data that are currently used
by the device for rendering the previous frame, as shown in Figure
28.3. Drivers have to avoid this problem by blocking the function until the desired data are not used anymore: this is called an
implicit synchronization.
在Valve和NVIDIA的"超越移植"中,它还说:
http://media.steampowered.com/apps/steamdevdays/slides/beyondporting.pdf
MAP_UNSYNCHRONIZED
- Avoids an application-GPU sync point (a CPU-GPU
sync point)- But causes the Client and Server threads to serialize
- This
forces all pending work in the server thread to complete- It’s quite
expensive (almost always needs to be avoided)
他们俩都指出glBufferSubData / glMapBuffer将阻止应用程序线程,而不仅仅是驱动程序线程。
为什么?
没有规则说驾驶员必须等待。它需要确保在使用旧内容进行绘制调用之前,缓冲区内容不会被修改。并且它需要使用在
让我们用一个典型的伪调用序列来说明问题,并标记这些调用以供以后解释:
1 2 3 4 5 | (1) glBindBuffer(buf) (2) glBufferSubData(dataA) (3) glDraw() (4) glBufferSubData(dataB) (5) glDraw() |
进行中的约束是:
-
在调用(2)返回后,驱动程序无法访问
dataA 指向的数据。 OpenGL规范允许调用者在调用返回之后对数据做任何想要的事情,因此驱动程序需要在调用返回之前使用它。 -
在调用(4)返回之后,驱动程序无法访问
dataB 指向的数据。 -
当
buf 的内容为dataA 时,需要执行由调用(3)产生的绘制命令。 -
buf 的内容为dataB 时,需要执行由调用(5)产生的绘制命令。
由于OpenGL固有的异步特性,有趣的情况是call(4)。假设此时已将
有多种方法可以处理这种情况。蛮力解决方案是简单地阻止调用(4)的执行,直到GPU完成调用(3)的绘制命令为止。那当然可以,但是可能会带来非常糟糕的性能影响。因为我们要等到GPU完成工作后再提交新工作,所以GPU可能会暂时闲置。这通常在管道中称为"气泡",这是非常不希望的。最重要的是,在调用返回之前,该应用程序也无法执行有用的工作。
解决此问题的最简单方法是,驱动程序在调用(4)中复制