VTK OpenGL对象(3D纹理)如何从CUDA中访问

3
有没有适当的方法可以访问VTK的低级OpenGL对象,以便使用openGL-CUDA/OpenCL互操作功能从CUDA/OpenCL内核中修改它们?具体来说,我想要从vtkOpenGLGPUVolumeRayCastMapper中获取GLuint(或unsigned int)成员,该成员指向存储数据集的Opengl 3D纹理对象,以将其绑定到CUDA Surface上,从而能够从我的CUDA内核中访问和修改其值。更多信息,请参见此处需要遵循的过程:http://rauwendaal.net/2011/12/02/writing-to-3d-opengl-textures-in-cuda-4-1-with-3d-surface-writes/,其中在步骤1和2中使用的texID对象相当于我想从VTK检索的内容。

初看vtkOpenGLGPUVolumeRayCastMapper函数,我没有发现容易的方法来做到这一点,除非可能创建一个vtkGPUVolumeRayCastMapper子类,但即使在这种情况下,我也不确定应该修改什么,因为我猜想其他成员依赖于3D纹理值,并且在修改后也应该进行更新。

那么,你知道有什么方法可以做到这一点吗?

非常感谢。

1个回答

1
子类化可能有效,但如果您愿意的话,可以避免使用它。重要的是您按正确的顺序调用GL/CUDA API。
首先,您必须使用以下方法向CUDA注册纹理:
cudaGraphicsGLRegisterImage(&cuda_graphics_resource, texture_handle,
GL_TEXTURE_3D, cudaGraphicsRegisterFlagsSurfaceLoadStore);

假设 texture_handle 是一个由调用 glGenTextures(...) 返回的 GLuint。

一旦您在 CUDA 中注册了纹理,就可以创建表面,该表面可以在内核中进行读写操作。

从这里开始,您唯一需要担心的是 vtk 不会在 cudaGraphicsMapResources(...) 和 cudaGraphicsUnmapResources(...) 之间使用纹理。其他所有内容都应该是标准的 CUDA。

此外,一旦将纹理映射到 CUDA 并在内核中写入,除了取消映射纹理之外,没有其他额外的工作。下次使用时,GL 将获取修改后的纹理。


谢谢您的回答,但那并不是我的疑问所在。主要问题涉及VTK,而不是Interop。 - Alex
首先,由于VTK GLuint被视为私有成员,因此无法访问。也许我可以创建一个子类并创建一个函数来获取访问权限。 即便如此,另一个问题出现了。由于VTK被认为处理静态体积,我的猜测是当创建VTK体积对象时,VTK会创建除纹理之外的其他数据。如果我仅从外部(CUDA)修改纹理,则存储在对象中的大部分附加数据将变得过时。因此,如何在从外部修改对象时处理其健壮性是一个大问题。 - Alex
我不熟悉VTK,但是你可以子类化,只要它是受保护的而不是私有的。如果像你所说的那样是私有的,你可以查询GL以获取当前绑定的纹理,但你必须知道VTK何时调用glBindTexture()。这假设你正在编写自己的着色器,并且如果VTK处理所有这些内容,则无法工作。据我所知,OpenGL中没有存储的任何信息会因在CUDA内核中编写texel值而失效。将(过时的)texels重新发送到OpenGL超过一次是计算成本高昂的,因此我怀疑VTK是否会这样做,但我不能确定。 - James Norton
实际上,这个变量是受保护的,所以我可以很容易地访问它。我提到的“无效”信息不是来自OpenGL,而是来自VTK,因为当一个新的体积被分配给它时,可能会计算一些加速结构和额外的计算(例如,与体积相关联的梯度场),由于VTK不知道这个CUDA修改,额外的数据会变得过时,因为它是在使用正常的VTK接口将初始体积分配给它时计算的。我想只有VTK专家才能回答这个问题:P。但还是谢谢! - Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接