如何在GL_STREAM_DRAW或GL_DYNAMIC_DRAW之间进行选择?

lve*_*lla 27 opengl-es vbo

我正在使用OpenGL ES 2.0,但我认为它也与非ES有关:如何知道在创建VBO时选择什么"用法"?

这个特殊的VBO将在完全更新之前使用1到4次,我不确定是否必须选择GL_STREAM_DRAW或GL_DYNAMIC_DRAW.

mur*_*003 21

那么,根据OpenGL API,你应该使用DYNAMIC_DRAW.

STREAM
当数据存储内容被修改一次并最多使用几次时,您应该使用STREAM_DRAW.

STATIC
当数据存储内容被修改一次并多次使用时,使用STATIC_DRAW.

DYNAMIC
当重复修改数据存储内容并多次使用时,使用DYNAMIC_DRAW.

确保使用glBufferSubData()更新VBO

  • 考虑到"最多几次"的措辞,我认为我应该使用`GL_STREAM_DRAW`,因为1到4次对我来说似乎有点...... (5认同)

dat*_*olf 11

用法标志是提示,而不是强制执行.换句话说:如果使用"错误"标志,事情就不会破坏.所以我建议你尝试所有3:STATIC_DRAW,STREAM_DRAW和DYNAMIC_DRAW并选择能够提供最佳性能的那个 - 而且它们很可能会打成平手.

  • 这是一个有用的实用技巧,但我仍然想知道两者的"预期"用途有何不同.一些GPU可能会利用它. (10认同)
  • 当他们创造区别时,他们可能会考虑到一些可能的优化,否则就没有意义.那些是什么? (3认同)
  • @datenwolf"这使得GL实现能够做出更明智的决策,这可能会对缓冲区对象的性能产生重大影响." 在我看来,非常具体和难以捉摸. (3认同)
  • @bobobobo:确实如此.事实上,在许多程序以错误的方式使用它们之后,AMD/ATI驱动程序完全忽略了这个提示,并通过分析程序的行为来选择最佳策略.如有疑问,我将使用DYNAMIC_DRAW作为默认值.OpenGL规范对此也不是很清楚.问题是,必须指定其中一个标志.将glHint的GL_DONT_CARE标志设置为有效也是有意义的. (3认同)

use*_*070 9

GL_STREAM_DRAW如果您要glBufferData()经常调用,则使用 -glBufferData()完全刷新缓冲区的内容,允许 opengl 进行一些优化,例如让 opengl 在旧数据仍在使用时上传新数据:Buffer Object Streaming

GL_STATIC_DRAW如果您不打算经常更改缓冲区的内容,则使用

GL_DYNAMIC_DRAW如果您要部分更改缓冲区,例如使用glBufferSubData().

据我所知,选择错误的选项可能会降低性能,但仅此而已。

这些选项很可能会影响内存的位置 - RAM 或 VRAM,以及有关使用分配的内存的一些策略(先组写入,然后发送数据,或立即写入)。RAM 可以由 CPU 直接写入,但从 GPU 读取(甚至不需要修改它)速度较慢,因为它必须通过 PCI-e。VRAM 是 GPU 本身上的 RAM;它不能直接由 CPU 写入(直到最近,或者除非你是 AMD)——相反,GPU 上的特殊硬件应该将数据从 RAM 批量复制到 VRAM。


der*_*ass 7

除了到目前为止给出的答案,虽然它与GLES没有任何直接关系,但我想从ARB_buffer_storage扩展的第2期粘贴这一点(与桌面GL 4.4一起介绍):

2)新标志不直接映射到glBufferData的参数,而不能用另一个表示.那有关系吗?

大多数应用程序usage出错了,无论如何它们只是提示.标志是必须遵循的硬性和快速规则.他们服务于不同的目的.这里的想法是允许实现不必再次猜测应用程序并执行较少的跟踪,并使应用程序具有更多控制.我们根据BufferStorage定义BufferData,使用最自由的允许标志(基本上,任何东西),但仍然将提示传递给实现,以允许它继续第二次猜测应用程序.

这些标志的问题一直是每个实现可能对如何优化使用提示所建议的不同路径有不同的想法,并且每个应用程序似乎对这些优化如何工作有不同的期望.

Nvidias桌面GL驱动程序将在调试配置文件中打印它为缓冲区对象做出的一些决定,特别是如果它们存储在客户端RAM中或直接存储在GPU上.玩这个时我得到了以下内容:

Buffer detailed info: Buffer object 5 (bound to GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations.
Buffer detailed info: Buffer object 5 (bound to GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_STATIC_DRAW) has been mapped in HOST memory.
Buffer detailed info: Buffer object 5 (bound to GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_STATIC_DRAW) stored in VIDEO memory has been updated.
Buffer detailed info: Buffer object 5 (bound to GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations.
Buffer detailed info: Buffer object 5 (bound to GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_STATIC_DRAW) has been mapped in HOST memory.
Buffer detailed info: Buffer object 5 (bound to GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_STATIC_DRAW) stored in SYSTEM HEAP memory has been updated.
Buffer detailed info: Buffer object 5 (bound to GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use SYSTEM HEAP memory as the source for buffer object operations.
Buffer detailed info: Buffer object 5 (bound to GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use SYSTEM HEAP memory as the source for buffer object operations.
Buffer detailed info: Buffer object 5 (bound to GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_STATIC_DRAW) has been mapped WRITE_ONLY in SYSTEM HEAP memory (fast).
Buffer detailed info: Buffer object 5 (bound to GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_STATIC_DRAW) has been mapped WRITE_ONLY in SYSTEM HEAP memory (fast).
Buffer detailed info: Buffer object 5 (bound to GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_STATIC_DRAW) has been mapped WRITE_ONLY in SYSTEM HEAP memory (fast).
Run Code Online (Sandbox Code Playgroud)

我在这里做的是使用PBO将纹理更新流传输到GPU,通过映射缓冲区每帧更新一次.这里的自然选择是使用GL_STREAM_DRAW,但我指定GL_STATIC_DRAW.驱动程序所做的是最初给我一些VRAM支持的缓冲区,并对我做的前两个更新进行I/O映射.但后来,它改变了主意,并使用了一个客户支持的缓冲区 - 如果我首先要求的话,那么我将得到的结果完全正确GL_STREAM_DRAW.我们在这里看到的是second guessing上面引用的文本的一个例子.

所有这些都是高度实现的.这也是上述GL扩展创建的部分原因 - 这将使程序员更多地控制这些事情.但是,据我所知,这个扩展在OpenGL ES领域是不可用的.