如何在CUDA中处理OpenGL立方体贴图纹理?
当要在CUDA内核中使用OpenGL纹理时,要做的一件事是从注册的图像和映射的资源(在这种情况下为纹理)中检索CUDA数组。在驱动程序API中,它是通过cuGraphicsSubResourceGetMappedArray
调用完成的,在2D纹理的情况下这不是问题。但是当谈到上述立方体贴图时,此函数的第三个参数需要一个面部枚举(如CU_CUBEMAP_FACE_POSITIVE_X
)。因此,出现了一些问题-当一个人通过这样的枚举时,返回的纹理数组将仅包含该特定面孔的数据,对吗?然后,如何整体使用多维数据集纹理来执行多维数据集映射,同样:
color = texCube(cubeMap, x, y, z);
还是在CUDA内核中不可能做到这一点,并且需要使用2D纹理以及正确的计算和用户代码采样?
好的-尽管解决方案并不像使用另一个CUDA函数那样简单,但我设法自己解决了该问题。
要将CUDA纹理参考与任何纹理绑定(无论是从OpenGL或D3D获得的纹理),必须提供一个映射到资源的CUDA数组,然后使用cuGraphicsSubResourceGetMappedArray
它来检索它。正如我在问题中提到的那样,在一维或二维纹理的情况下很简单。但是使用其他可用类型则更为复杂。
在任何时候,我们都需要引用绑定到的CUDA数组。多维数据集贴图纹理也是如此。但是在这种情况下,阵列必须是3D阵列。问题在于,CUDA驱动程序API仅提供上述功能来从此类纹理资源中检索单个图层,并将其映射到一个二维数组。为了获得我们想要的东西,我们必须使自己成为包含所有图层(如果是立方体贴图,则是面)的3D数组。
首先,我们必须使用上述函数为每个图层/面获取数组。下一步是通过调用来创建3D数组cuArray3DCreate
,并提供适当的参数集(大小/层数,详细程度,数据格式,每个texel的通道数和一些标记)。然后,我们必须通过一系列调用,将图层的数组复制到3D cuMemcpy3D
,每个图层/面数组一个。
最后,我们将目标CUDA纹理参考设置为cuTexRefSetArray
,并提供我们创建并复制到的3D数组。在设备代码内部,我们创建了具有适当纹理类型和模式(float4和立方体贴图)的引用,并使用对其进行了采样texCubemap
。
在下面,我放了一个函数的片段,它可以完成所有操作,并在CIRT存储库中提供了完整的内容(cirt_server.c文件,function 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纹理配合使用。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句