如何在CUDA中处理OpenGL立方体贴图纹理?
当想要在CUDA内核中使用OpenGL纹理时,要做的一件事就是从已注册的图像和映射资源中检索CUDA数组,在本例中是一个纹理。在驱动程序API中,它由cuGraphicsSubResourceGetMappedArray
调用完成,在2D纹理的情况下,这不是问题。但在谈到上述立方体贴图时,此函数的第三个参数需要面部枚举(如CU_CUBEMAP_FACE_POSITIVE_X
)。因此出现了一些问题 - 当一个人通过这样的枚举时,返回的纹理数组将仅包含该特定面的数据,对吧?然后如何使用立方体纹理作为一个整体,执行立方体映射,同样:
color = texCube(cubeMap, x, y, z);
或者在CUDA内核中不可能这样做,需要在用户代码中使用2D纹理和适当的计算和采样吗?
答案 0 :(得分:2)
好的 - 我自己设法解决了这个问题,虽然解决方案并不像使用其他CUDA功能那么简单。
要将CUDA纹理参考与任何纹理绑定,无论是从OpenGL还是D3D获取,都必须提供映射到资源的CUDA数组,使用cuGraphicsSubResourceGetMappedArray
来检索它。正如我在问题中提到的,在一维或二维纹理的情况下很简单。但是对于其他可用类型,它更复杂。
我们需要一个引用绑定的CUDA数组。立方体贴图纹理也是如此。但在这种情况下,阵列必须是3D阵列。问题是CUDA驱动程序API仅提供上述功能以从这样的纹理资源中检索单个图层,并将其映射到单个二维数组。为了得到我们想要的东西,我们必须使自己成为包含所有图层的3D数组(或者在立方体贴图的情况下使用面)。
首先,我们必须使用上面的函数为每个图层/面部获取数组。下一步是通过调用cuArray3DCreate
创建3D数组,并提供适当的参数集(大小/层数,细节级别,数据格式,每个纹素的通道数和一些标志)。然后我们必须复制图层'通过对cuMemcpy3D
的一系列调用,将数组传递给3D,每个图层/面阵列都有一个。
最后,我们使用cuTexRefSetArray
设置目标CUDA纹理参考,并使用我们创建并复制到的3D数组。在设备代码内部,我们使用适当的纹理类型和模式(float4和立方体贴图)创建一个引用,并使用texCubemap
对其进行采样。
下面我放了一个函数的片段,它完成了所有这些,在CIRT Repository(cirt_server.c文件,函数cirtTexImage3D
)中全长可用。
//...
if (result)
{
// Create a 3D array...
CUDA_ARRAY3D_DESCRIPTOR layeredTextureDescr;
layeredTextureDescr.Width = w;
layeredTextureDescr.Height = h;
layeredTextureDescr.Depth = d;
layeredTextureDescr.Format = map_type_to_format(type);
layeredTextureDescr.NumChannels = format == CIRT_RGB ? CIRT_RGBA : format;
layeredTextureDescr.Flags = map_target_to_flags(target);
if (result) result = LogCUDADriverCall(cuArray3DCreate(&hTexRefArray, &layeredTextureDescr),
FUN_NAME(": cuArray3DCreate_tex3D"), __FILE_LINE__);
// Copy the acquired layer/face arrays into the collective 3D one...
CUDA_MEMCPY3D layerCopyDescr;
layerCopyDescr.srcMemoryType = CU_MEMORYTYPE_ARRAY;
layerCopyDescr.srcXInBytes = 0;
layerCopyDescr.srcZ = 0;
layerCopyDescr.srcY = 0;
layerCopyDescr.srcLOD = 0;
layerCopyDescr.dstMemoryType = CU_MEMORYTYPE_ARRAY;
layerCopyDescr.dstLOD = 0;
layerCopyDescr.WidthInBytes = layeredTextureDescr.NumChannels * w;
layerCopyDescr.Height = h;
layerCopyDescr.Depth = target == CIRT_TEXTURE_CUBE_MAP ? 1 : d;
layerCopyDescr.dstArray = hTexRefArray;
for (i = 0; i < num_layers; ++i)
{
layer = ((num_layers == 6) ? CU_CUBEMAP_FACE_POSITIVE_X + i : i);
layerCopyDescr.dstXInBytes = 0;
layerCopyDescr.dstY = 0;
layerCopyDescr.dstZ = i;
layerCopyDescr.srcArray = hLayres[i];
if (result) result = LogCUDADriverCall(cuMemcpy3D(&layerCopyDescr),
FUN_NAME(": cuMemcpy3D_tex3D"), __FILE_LINE__);
}
// Finally bind the 3D array with texture reference...
if (result) LogCUDADriverCall(cuTexRefSetArray(hTexRef, hTexRefArray, CU_TRSA_OVERRIDE_FORMAT),
FUN_NAME(": cuTexRefSetArray_tex3D"), __FILE_LINE__);
if (hLayres)
free(hLayres);
if (result)
current->m_oTextureManager.m_cuTextureRes[current->m_oTextureManager.m_nTexCount++] = hTexResource;
}
//...
我现在只使用立方体贴图检查它,但它也应该可以正常使用3D纹理。