【发布时间】:2022-01-13 21:33:01
【问题描述】:
我想将源自 OpenGL 纹理的 3D cudaArray 的内容复制到“经典”数组,反之亦然。
注意: 在下面的 sn-ps 中,为了清楚起见,省略了错误检查。
cudaArray 是这样“分配”的:
cudaArray* texture_array {nullptr};
cudaGraphicsResource* resource{nullptr};
cudaGraphicsGLRegisterImage(&resource, texture.id, GL_TEXTURE_3D, cudaGraphicsRegisterFlagsNone);
cudaGraphicsMapResources(1, &resource, cuda_stream);
cudaGraphicsSubResourceGetMappedArray(&texture_array, resource, array_index, mipmap);
此操作成功,因为我可以使用
cudaArrayGetInfo(&description, &extent, &flags, texture_array) 并在此处使用512 x 512 x 122 纹理以uint16 格式获取类似于以下示例的内容。
//C-style pseudo-code
description
{
.x = 16,
.y = 0,
.z = 0,
.w = 0,
.f = cudaChannelFormatKindUnsigned,
};
extent
{
.width = 512,
.height = 512,
.depth = 122
};
flags = 0;
第一次尝试:线性数组
阅读this answer to a post asking about pitched memory 后,我的第一次尝试是使用cudaMemcpy3D 并模拟一个以pitch 为行长度(以字节为单位)的倾斜数组,如下所示:
std::uint8_t* linear_array{nullptr};
const cudaExtent extent =
{
.width = texture.width * texture.pixel_format_byte_size,
.height = texture.height,
.depth = texture.depth
};
cudaMalloc(&linear_array, extent.width * extent.height * extent.depth);
然后像这样复制到它:
const cudaMemcpy3DParms copy_info =
{
.srcArray = texture_array,
.srcPos =
{
.x = 0,
.y = 0,
.z = 0
},
.srcPtr =
{
.ptr = nullptr,
.pitch = 0,
.xsize = 0,
.ysize = 0
},
.dstArray = nullptr,
.dstPos =
{
.x = 0,
.y = 0,
.z = 0
},
.dstPtr =
{
.ptr = linear_array,
.pitch = extent.width,
.xsize = texture.width,
.ysize = texture.height,
},
.extent = extent,
.kind = cudaMemcpyDefault,
};
cudaMemcpy3D(©_info)
然而,上面的代码在调用cudaMemcpy3D 时会生成一个cudaErrorInvalidValue。
不用说,如果我将两者颠倒过来(源变成目标,反之亦然),也会发生同样的事情。
第二次尝试:倾斜阵列
对我来说有点复杂,因为我打算修改 __global__ 函数中的数据,但无论如何。
同样,我分配一个(真实的)倾斜数组,如下所示:
cudaPitchedPtr ptr;
const cudaExtent extent =
{
.width = texture.width * texture.pixel_format_byte_size,
.height = texture.height,
.depth = texture.depth,
};
cudaMalloc3D(&ptr, extent);
并像这样复制到它:
const cudaMemcpy3DParms copy_info =
{
.srcArray = texture_array,
.srcPos =
{
.x = 0,
.y = 0,
.z = 0
},
.srcPtr =
{
.ptr = nullptr,
.pitch = 0,
.xsize = 0,
.ysize = 0
},
.dstArray = nullptr,
.dstPos =
{
.x = 0,
.y = 0,
.z = 0
},
.dstPtr = ptr,
.extent = extent,
.kind = cudaMemcpyDefault
};
cudaMemcpy3D(©_info);
但我也收到了cudaErrorInvalidValue 的电话,cudaMemcpy3D。
我做错了什么?
当数组是来自图形 API 的纹理时,API 的限制是否禁止我调用 cudaMemcpy3D?如果是这样,我该怎么办?
【问题讨论】: