【问题标题】:OpenGL 4.0 GPU Draw Feature?OpenGL 4.0 GPU 绘图功能?
【发布时间】:2011-02-18 22:33:55
【问题描述】:

在 Wikipedia 和其他来源对 OpenGL 4.0 的描述中,我读到了有关此功能的信息:

绘制由 OpenGL 或 OpenCL 等外部 API 生成的数据,无需 CPU 干预。

这是指什么?

编辑

似乎这一定是指 Draw_Indirect,我相信以某种方式扩展绘图阶段以包括来自着色器程序或互操作程序的反馈(基本上是 OpenCL/CUDA) 看起来好像有一些注意事项和技巧可以让调用在第二次运行后继续留在 GPU 上的任何延长时间,但应该是可能的。

如果有人可以提供更多关于在没有 CPU 的情况下使用绘图命令的信息,或者可以更好地描述间接绘图,请随时这样做。将不胜感激。

【问题讨论】:

    标签: opengl gpgpu hardware-acceleration opengl-4


    【解决方案1】:

    我相信您可能指的是GL_ARB_draw_indirect 功能,该功能允许 OpenGL 从 GPU 缓冲区对象中获取 DrawArrays 或 DrawElements 参数,这些参数可以由 OpenGL 或 OpenCL 填充。

    如果我没记错的话,它包含在核心 OpenGL 4 中。

    【讨论】:

    • 到目前为止,我只看到在网络服务器正在为客户端计算机处理一些渲染的关系中使用它。
    • @Garet - 我不确定你的意思。这是您预见的用法,还是您发现的实际示例用法?
    • 这些只是我在谷歌上搜索到的 draw_indirect 示例。我还没有看到对该功能的非常可靠的描述。
    • @garet - 我很想知道你发现了什么;我自己还没有看到任何具体的用法。 GPU 剔除等算法可以从此功能中受益,例如请参阅 rastergrid.com/blog/2010/10/… 和此博客上的其他一些帖子
    • 好吧,我似乎找不到我之前找到的两个相同的例子。。在VirtualGL 中只是对它的模糊引用我确实找到了一点关于directx 的draw_indirect 的信息,即应该是相似的,而且在g-truc.net 上看起来这一定是我猜的功能。相当稀疏的信息。
    【解决方案2】:

    我还没有弄清楚 OpenGL 4.0 是如何使这个功能发挥作用的,因为据我所知,它以前就存在过。我不确定这是否能回答你的问题,但无论如何我会告诉你我对这个主题的了解。

    它指的是OpenGL以外的其他库,例如OpenCL或CUDA,将一些数据直接生成到显卡的内存中,然后OpenGL从其他库离开的地方继续,并将该数据用作

    • 像素缓冲区对象 (PBO),当他们想要将数据原样绘制到屏幕上时
    • 当他们想要将图形数据用作其他场景的一部分时的纹理
    • 当他们想要使用生成的数据作为顶点着色器的一些任意属性输入时,顶点缓冲区对象 (VBO)。 (其中一个例子可能是使用 CUDA 模拟并使用 OpenGL 渲染的粒子系统)

    在这种情况下,最好将数据一直保存在显卡中而不是到处复制,尤其是不要通过 CPU 复制,因为 PCIe 总线与内存相比非常慢显卡总线。

    下面是一些示例代码,可以使用 CUDA 和 OpenGL 来实现 VBO 和 PBO:

    // in the beginning
    glGenBuffers(&id, 1);
    
    // for every frame
    cudaGLRegisterBufferObject(id);
    CUdeviceptr ptr;
    cudaGLMapBufferObject(&ptr, id);
    // <launch kernel here>
    cudaGLUnmapBufferObject(id);
    // <now use the buffer "id" with OpenGL>
    cudaGLUnregisterBufferObject(id);
    

    以下是如何将数据加载到纹理中:

    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, id);
    glBindTexture(GL_TEXTURE_2D, your_tex_id);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, 0);
    

    另外请注意,如果您使用一些更不寻常的格式而不是 GL_RGBA,它可能会更慢,因为它必须转换所有值。

    我不知道 OpenCL,但想法是一样的。只有函数名不同。

    做同样事情的另一种方法是所谓的主机固定内存。在这种方法中,您将一些 CPU 内存地址范围映射到显卡内存。

    【讨论】:

    • 好吧,我一直在使用 VBO 等来获取/保存图形内存上的数据,但您仍然必须从 CPU 发出 DrawArrays() 或 DrawElements() 或类似的东西。 4.0 规范和许多其他地方都在谈论一些新功能,也许它只是几何着色器......不确定,但我认为 VBO 从 1.4 左右就已经存在了。 OpenCL Interop 非常相似,只需在初始化后处理映射即可。
    【解决方案3】:

    要了解此功能是什么,您必须了解之前的工作原理。

    在 4.0 之前,OpenCL 可以用数据填充 OpenGL 缓冲区对象。事实上,常规的 OpenGL 命令可以用数据填充 OpenGL 缓冲区对象,或者通过变换反馈或通过渲染到buffer texture。该数据可以是用于渲染的顶点数据。

    只有 CPU 可以启动顶点数据的渲染(通过调用 glDraw* functions. 之一即使如此,这里也不需要显式同步(在任何 OpenCL/OpenGL 互操作要求之外)。具体来说,CPU不必读取由 GPU 操作写入的数据。

    但这会导致一个问题。如果 OpenCL 或任何 GPU 操作总是将已知数量的顶点写入缓冲区,那么一切都很好。然而,这必须是这样的。 GPU 进程通常希望写入任意数量的顶点。显然需要有一个最大限制(缓冲区的大小)。但除此之外,你希望它能够写任何它想要的东西。

    问题是 OpenCL 决定了要写多少。但是CPU 现在需要这个数字才能使用glDraw 函数之一。如果 OpenCL 写入了 22000 个顶点,那么 CPU 需要将 22000 个传递给glDrawArrays

    ARB_draw_indirect(GL 4.0 的核心功能)的作用是允许 GPU 进程将值写入缓冲区对象,该对象表示您将传递给 glDraw* 函数的参数。唯一未涵盖的参数是原始类型。

    请注意,CPU 仍然控制渲染发生的时间。 CPU 仍然决定从哪些缓冲区中提取顶点数据。所以 OpenCL 可以编写其中的几个 glDraw* 命令,但是直到 CPU 真正为其中一个调用 glDrawElementsIndirect 之前,实际上什么都不会被渲染。

    所以你可以做的是运行一个 OpenCL 进程,它将一些数据写入现有的缓冲区对象。然后使用通常的顶点设置绑定这些缓冲区,就像使用 VAO 一样。 OpenCL 进程会将适当的渲染命令数据写入其他缓冲区对象,您将绑定为间接缓冲区。然后你使用glDraw*Indirect 来渲染这些命令。

    CPU 在任何时候都不必从 GPU 读回数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-13
      • 1970-01-01
      相关资源
      最近更新 更多