4

我正在研究 3D 模拟(现在是 2D),我使用 CUDA 进行计算,使用 OpenGL 进行渲染。我的问题涉及 CUDA 和 OpenGL 之间的互操作性。据我所见,有两种通用方法可以做到这一点:

第一个是使用映射到 CUDA 全局内存然后复制到 OpenGL 纹理的像素缓冲区对象(或顶点缓冲区对象)。据说这是一种非常快速的方法。

第二个是将纹理对象直接复制到 CUDA 纹理内存。从那时起我可以使用所有纹理内存功能,如纹理缓存等,这也将非常好。

现在,有人可以向我解释这两种方法之间的一般区别是什么吗?以及它们每个通常用于什么样的情况?

4

1 回答 1

5

整个区别就像你说的,在纹理缓存中。因此,在这两种方法之间进行选择取决于您是否希望在可视化中利用纹理缓存。让我们看一些常见的情况:

a) 如果你想计算一个表面是如何变形的(例如水的表面,或者可能是一些弹性变形)并且你需要知道表面多边形网格的新顶点,那么你通常会使用缓冲区(第一),除非您不需要在此处复制到 OpenGL 纹理。实际上这里不涉及复制,您只需引用 CUDA 中的缓冲区并将其用作 gl 缓冲区。

b) 如果你有一个粒子模拟并且需要知道更新后的粒子的位置,你也可以在上面的例子中使用一个缓冲区。

c)如果您有一个有限元网格模拟,其中空间中的每个固定体积单元都会获得一个新值,并且您需要通过体积渲染或等值面对其进行可视化,这里您将需要使用纹理对象(2D 或 3D,具体取决于模拟的维度),因为当你投射光线,甚至生成流线时,你几乎总是需要立即缓存相邻的纹素。并且您可以避免在此处进行任何复制,因为在上述方法中您也可以直接从 OpenGL 引用一些 CUDA 纹理内存(cudaArray)。您将使用这些调用来做到这一点:

cudaGraphicsGLRegisterImage( &myCudaGraphicsResource, textureNameFromGL, GL_TEXTURE_3D,...)
...
cudaGraphicsMapResources(1, myCudaGraphicsResource)
cudaGraphicsSubResourceGetMappedArray(&mycudaArray, myCudaGraphicsResource, 0, 0)
cudaGraphicsUnMapResources(1, myCudaGraphicsResource)

因此 CUDA 中的纹理数据可以由 mycudaArray 引用,而 OpenGL 中的相同内存可以由 textureNameFromGL 引用。

从缓冲区复制到纹理是一个坏主意,因为如果您需要此数据进行纹理缓存,您将进行额外的复制。在支持纹理互操作之前,这在早期版本的 CUDA 中更流行

您也可以在 a) 和 b) 用例中使用纹理。对于某些硬件,它甚至可能运行得更快,但这非常依赖于硬件。还要记住,纹理读取也会应用缩小和放大过滤器,如果您要查找的只是存储在缓冲区中的精确值,则这是额外的工作。

要与 CUDA 和 OpenGL 共享纹理资源,请参阅此示例

https://github.com/nvpro-samples/gl_cuda_interop_pingpong_st

于 2013-05-07T12:12:38.813 回答