为什么glBufferSubData需要等到glDrawElements不使用VBO为止? [英] Why glBufferSubData need to wait until the VBO is not used by glDrawElements?

查看:170
本文介绍了为什么glBufferSubData需要等到glDrawElements不使用VBO为止?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在OpenGL Insights中,它表示"OpenGL驱动程序必须等待,因为使用了VBO 通过glDrawElements从上一帧开始".

In OpenGL Insights, it says that "OpenGL driver has to wait because VBO is used by glDrawElements from previous frame".

这让我很困惑. 据我所知,glBufferSubData会将数据复制到临时内存中,然后在以后传输到GPU.

That confused me a lot. As I know, glBufferSubData will copy the data to temporary memory, and then transfer to GPU later.

那么为什么驾驶员仍然需要等待?它可以仅将Transfer命令附加到命令队列中,从而将数据传输到GPU的操作延迟到glDrawElements完成,对吧?

So why the driver still need to wait? it can just append the Transfer command to the command queue, delaying transfering the data to GPU until the glDrawElements is finished, right?

--------添加----------------------------------------- ---------------------------------

----- ADDED --------------------------------------------------------------------------

在OpenGL Insights中,它表示:

In OpenGL Insights, it says:

http://www.seas.upenn.edu/~ pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf (第397页)

但是,当使用glBufferSubData或glMapBuffer [Range]时,没有任何内容 API本身阻止我们修改当前使用的数据 由设备渲染前一帧,如图 28.3. 驱动程序必须通过阻止该功能直到不再使用所需的数据来避免此问题:这被称为 隐式同步.

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,它说:

And also in "Beyond Porting" by Valve & NVIDIA, it says:

http://media.steampowered.com/apps/steamdevdays/slides/beyondporting.pdf

MAP_UNSYNCHRONIZED

MAP_UNSYNCHRONIZED

  • 避免应用程序与GPU的同步点(CPU-GPU 同步点)
  • 但是导致客户端和服务器线程进行序列化
    • 这 强制完成服务器线程中所有待处理的工作
    • 相当 昂贵(几乎总是需要避免)
    • 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将阻止应用程序线程,而不仅仅是驱动程序线程.

      Both of them pointed out that glBufferSubData/glMapBuffer will block the application thread, not just the driver thread.

      为什么?

      推荐答案

      没有规则说驾驶员必须等待.它需要确保在使用旧内容进行绘制调用之前,缓冲区内容不会被修改.并且它需要使用glBufferSubData()调用返回之前,调用方传递的数据.只要结果正确无误,驱动程序中的任何实现都是公平的游戏.

      There is no rule saying that the driver has to wait. It needs to ensure that buffer content is not modified before draw calls using the old content have finished executing. And it needs to consume the data that the caller passed in before the glBufferSubData() call returns. As long as the resulting behavior is correct, any implementation in the driver is fair game.

      让我们用一个典型的伪调用序列来说明问题,并标记这些调用以供以后解释:

      Let's illustrate the problem with a typical pseudo-call sequence, labelling the calls for later explanation:

      (1) glBindBuffer(buf)
      (2) glBufferSubData(dataA)
      (3) glDraw()
      (4) glBufferSubData(dataB)
      (5) glDraw()
      

      比赛中的限制因素是:

      • 在调用(2)返回后,驱动程序无法访问dataA指向的数据. OpenGL规范允许调用者在调用返回之后对数据做任何想要的事情,因此驱动程序需要在调用返回之前将其消耗掉.
      • 调用(4)返回后,驱动程序无法访问dataB指向的数据.
      • buf的内容为dataA时,需要执行由调用(3)产生的绘制命令.
      • buf的内容为dataB时,需要执行由调用(5)产生的绘制命令.
      • The data pointed to by dataA cannot be accessed by the driver after call (2) returns. The OpenGL specs allow the caller to do anything it wants with the data after the call returns, so it needs to be consumed by the driver before the call returns.
      • The data pointed to by dataB cannot be accessed by the driver after call (4) returns.
      • The draw command resulting from call (3) needs to be executed while the content of buf is dataA.
      • The draw command resulting from call (5) needs to be executed while the content of buf is dataB.

      由于OpenGL具有固有的异步特性,因此有趣的情况是调用(4).假设此时已将dataA存储在buf中,并且调用(3)的draw命令已排队等待GPU执行.但是我们不能依靠GPU执行过该绘制命令.因此我们无法将dataB存储在buf中,因为待处理的绘制命令必须由GPU执行,而dataA仍存储在buf中.但是在消耗dataB之前,我们无法从通话中返回.

      Due to the inherently asynchronous nature of OpenGL, the interesting case is call (4). Let's say that dataA has been stored in buf at this point in time, and the draw command for call (3) has been queued up for execution by the GPU. But we can't rely on the GPU having executed that draw command yet. So we can't store dataB in buf because the pending draw command has to be executed by the GPU while dataA is still stored in buf. But we can't return from the call before we consumed dataB.

      有多种方法可以处理这种情况.蛮力解决方案是简单地阻止调用(4)的执行,直到GPU完成调用(3)的绘制命令为止.那当然可以,但是可能会带来非常糟糕的性能影响.因为我们要等到GPU完成工作后再提交新工作,所以GPU可能会暂时处于空闲状态.这通常在管道中称为气泡",这是非常不希望的.最重要的是,在调用返回之前,该应用程序也被阻止执行有用的工作.

      There are various approaches for handling this situation. The brute force solution is to simply block the execution of call (4) until the GPU has finished executing the draw command from call (3). That will certainly work, but can have very bad performance implications. Because we wait until the GPU completed work before we submit new work, the GPU will likely go temporarily idle. This is often called a "bubble" in the pipeline, and is very undesirable. On top of that, the application is also blocked from doing useful work until the call returns.

      解决此问题的最简单方法是,驱动程序在调用(4)中复制dataB,然后在GPU完成调用中的绘制命令之后将数据副本复制到buf中(3 ),但在执行调用(5)的draw命令之前.不利之处在于,它涉及额外的数据复制,但是防止管道气泡通常是值得的.

      The simplest way to work around this is for the driver to copy dataB in call (4), and later place this copy of the data in buf, after the GPU has completed the draw command from call (3), but before the draw command from call (5) is executed. The downside is that it involves additional data copying, but it's often well worth it to prevent the pipeline bubbles.

      这篇关于为什么glBufferSubData需要等到glDrawElements不使用VBO为止?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆