为什么glBufferSubData需要等到VBO不被glDrawElements使用?

2024-02-08

在 OpenGL Insights 中,它说“OpenGL 驱动程序必须等待,因为使用了 VBO 由上一帧的 glDrawElements 绘制”。

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

那么为什么司机还需要等待呢?它可以只将 Transfer 命令附加到命令队列,延迟将数据传输到 GPU,直到 glDrawElements 完成,对吧?

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

在 OpenGL Insights 中,它说:

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

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

Valve 和 NVIDIA 的“Beyond Porting”中也提到:

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

MAP_UNSYNCHRONIZED

  • 避免应用程序-GPU 同步点(CPU-GPU 同步点)
  • But causes the Client and Server threads to serialize
    • 这 强制服务器线程中所有挂起的工作完成
    • 相当 昂贵(几乎总是需要避免)

没有规定司机必须等待。它需要确保在使用旧内容的绘制调用完成执行之前缓冲区内容不被修改。并且需要消耗调用者之前传入的数据glBufferSubData()呼叫返回。只要结果行为正确,驱动程序中的任何实现都是公平的。

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

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

游戏中的限制条件是:

  • 所指向的数据dataA调用 (2) 返回后,驱动程序无法访问。 OpenGL 规范允许调用者在调用返回后对数据执行任何操作,因此驱动程序需要在调用返回之前使用数据。
  • 所指向的数据dataB调用 (4) 返回后,驱动程序无法访问。
  • 需要执行调用(3)产生的绘制命令,同时执行buf is dataA.
  • 需要执行调用(5)产生的绘制命令,同时buf is dataB.

由于 OpenGL 固有的异步特性,有趣的情况是调用 (4)。这么说吧dataA已存储在buf此时,调用(3)的绘制命令已排队等待GPU执行。但我们还不能依赖 GPU 执行该绘制命令。所以我们无法存储dataB in buf因为挂起的绘制命令必须由 GPU 执行dataA仍然存储在buf。但我们无法在消费之前从调用中返回dataB.

有多种方法可以处理这种情况。强力解决方案是简单地阻止调用 (4) 的执行,直到 GPU 完成执行调用 (3) 中的绘制命令。这肯定会起作用,但可能会产生非常糟糕的性能影响。因为我们要等到 GPU 完成工作才提交新工作,所以 GPU 可能会暂时空闲。这通常被称为管道中的“泡沫”,并且是非常不可取的。最重要的是,在调用返回之前,应用程序也被阻止执行有用的工作。

解决此问题的最简单方法是让驱动程序复制dataB在调用 (4) 中,然后将此数据副本放入buf,在 GPU 完成调用 (3) 中的绘制命令之后,但在执行调用 (5) 中的绘制命令之前。缺点是它涉及额外的数据复制,但为了防止管道泡沫通常是值得的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么glBufferSubData需要等到VBO不被glDrawElements使用? 的相关文章

  • 为什么 OpenGL 有远裁剪平面,以及使用什么惯用法来处理这个问题?

    我一直在学习 OpenGL 持续困扰我的一个话题是远裁剪平面 虽然我可以理解近剪裁平面和侧剪裁平面 它们永远不会产生任何实际效果 因为它们之外的对象无论如何都不会被渲染 背后的推理 但远剪裁平面似乎只是一个烦恼 由于 OpenGL 背后的人
  • LibGDX纹理混合与OpenGL混合功能

    在 libGdx 中 我试图创建一个成形纹理 采用完全可见的矩形纹理并将其遮罩以获得成形纹理 如下所示 在这里我在矩形上测试它 但我想在任何形状上使用它 我调查过本教程 http www learnopengles com tag addi
  • 使用 glGetFloatv 检索 pyglet 中的模型视图矩阵

    我正在使用 pyglet 在 python 中进行 3D 可视化 并且需要检索模型视图和投影矩阵来进行一些选择 我使用以下方式定义我的窗口 from pyglet gl import from pyglet window import wi
  • OpenGL中背景对象绘制在前景对象前面?

    为了测试目的 我们假设我画了 2 个茶壶glutSolidTeapot 像这样 glColor3f 1 0f 0 0f 0 0f Red teapot glutWireTeapot 1 0f glColor3f 0 0f 1 0f 0 0f
  • 移动/调整大小期间 opengl 窗口冻结

    我正在使用 LWJGL 开发游戏 移动窗口时 计划将来添加调整大小代码 渲染循环冻结 我希望它在移动时继续以某种方式运行 LWJGL 不包括 glutMainLoop Display属于OpenGL 而不是Java 相关代码 regular
  • Windows下使用GLEW使用OpenGL扩展

    我一直在 Windows 上使用 OpenGL 扩展痛苦的方式 https stackoverflow com questions 14413 using opengl extensions on windows GLEW 是更简单的方法吗
  • 如何计算正切和副法线?

    谈谈OpenGL着色语言 GLSL 中的凹凸贴图 镜面高光之类的东西 I have 顶点数组 例如 0 2 0 5 0 1 0 2 0 4 0 5 法线数组 例如 0 0 0 0 1 0 0 0 1 0 0 0 世界空间中点光源的位置 例如
  • 为什么我的 CAOpenGLLayer 更新速度比之前的 NSOpenGLView 慢?

    我有一个在 Mac OS X 上渲染 OpenGL 内容的应用程序 最初它渲染到 NSOpenGLView 然后我将其更改为渲染到 CAOpenGLLayer 子类 当我这样做时 我看到了巨大的性能损失 帧速率减半 鼠标响应能力降低 卡顿
  • 如何在OpenGL中像这样绘制连接的带状线

    我想用以下方式绘制一系列连接线 GL LINE STRIP 我尝试过自己编写代码 但没有得到想要的结果 所以我来到这里 帮助我找出我错在哪里 这里我只给出我的draw 函数 glBegin GL LINE STRIP glVertex2f
  • WGL:没有双缓冲 + 多重采样 = 失败?

    我通常使用创建像素格式wglChoosePixelFormatARB 与这些论点 除其他外 WGL DOUBLE BUFFER ARB GL TRUE WGL SAMPLE BUFFERS ARB GL TRUE WGL SAMPLES A
  • 无法在 QGLWidget 中设置所需的 OpenGL 版本

    我正在尝试在 Qt 4 8 2 中使用 QGLWidget 我注意到 QGLWidget 创建的默认上下文不显示 OpenGL 3 1 以上的任何输出 Qt wiki 有一个教程 http qt project org wiki How t
  • 为什么 cudaGLSetGLDevice 失败,即使它是在 main 函数的第一行中调用的

    我想使用 OpenGL 和 CUDA 之间的互操作性 我知道 正如一些教程所说 第一步是选择设备 但是 当我在主函数的第一行中调用 cudaGLSetGLDevice 0 时 程序退出并显示信息 cudaSafeCall 运行时 API 错
  • Shader的功能参数表现

    我试图了解如何在着色器语言中实现传递参数 我读过几篇文章和文档 但仍然有一些疑问 特别是我试图理解与C 函数调用 特别强调性能 之间略有差异HLSL Cg and GLSL但我猜下划线的实现非常相似 到目前为止我所理解的 除非另有说明 函数
  • 使用 OpenGL 渲染 QImage

    与我相关的其他问题 https stackoverflow com questions 20126354 render qimage from sooffscreenrenderer in qglwidget 我认为更核心的问题是 如何渲染
  • OpenGL 缓冲区、glFlush 和 glutSwapBuffers()

    使用之间有什么区别吗 glutInitDisplayMode GLUT SINGLE GLUT RGB with glFlush and glutInitDisplayMode GLUT DOUBLE GLUT RGB with glutS
  • 如何创建自己的 openGL 上下文并将其绑定到 GLCanvas?

    所以当我开始掌握java时 paint Graphics g 我继续创建自己的渲染方法 但我必须了解缓冲区策略以及如何 获取 图形 所以现在我在学习openGL 我必须掌握方法 Override public void display GL
  • nVidia 和 ATI 之间的 OpenGL 渲染差异

    最近 我将 ATI 驱动程序 我使用的是 HD7970 更新为最新版本 但我的 OpenGL 项目的一些对象停止工作 更重要的是 他们适用于 nVidia 最新驱动程序 在 960m 上测试 ATI 和 nVidia 渲染管道之间有什么我应
  • glTranslatef 不在 glBegin .. glEnd 中工作

    我正在尝试并排绘制不同颜色的两个方块 我的问题是我无法让 glTranslatef 将第二个方块向右移动 第二个方块只是绘制在第一个方块上 void display void glClear GL COLOR BUFFER BIT glMa
  • 新显卡上的 nvoglv32.dll 中的绘制调用崩溃

    几天前 由于一些硬件更改 我设置了计算机并安装了新的 Windows 8 副本 其中 我将显卡从 Radeon HD 7870 更改为 Nvidia GTX 660 再次设置 Visual Studio 11 后 我从 Github 下载了
  • 并排显示图像的一半 - OpenGL

    我为两个图像创建了两个纹理 现在我想在opengl中按图像2的左侧部分 完整的图像1 图像2的右侧部分的顺序显示该纹理 我已经做了如下 Image1 显示在 opengl 屏幕的中央 但屏幕的左右部分不正确 应分别显示 image2 的左侧

随机推荐