复制从 OpenGL 纹理获得的 3D cudaArray 的内容
Copy the contents of a 3D cudaArray obtained from an OpenGL texture
我想将源自 OpenGL 纹理的 3D cudaArray
的内容复制到“经典”数组,反之亦然。
Note:
In the following snippets, errors checks are omitted for clarity.
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)
并使用格式为 uint16
.
的 512 x 512 x 122
纹理获取类似于以下示例的内容
//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
?如果是这样,我该怎么办?
经过各种测试(复制到另一个cudaArray
和其他类似的东西),问题似乎来自误解。
文档明确指出:
" If a CUDA array is participating in the copy, the extent is defined in terms of that array's elements".
因此,copy_info.extent
必须是(在我的上下文中)cudaArrayGetInfo
检索到的范围。
我想将源自 OpenGL 纹理的 3D cudaArray
的内容复制到“经典”数组,反之亦然。
Note: In the following snippets, errors checks are omitted for clarity.
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)
并使用格式为 uint16
.
512 x 512 x 122
纹理获取类似于以下示例的内容
//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
?如果是这样,我该怎么办?
经过各种测试(复制到另一个cudaArray
和其他类似的东西),问题似乎来自误解。
文档明确指出:
" If a CUDA array is participating in the copy, the extent is defined in terms of that array's elements".
因此,copy_info.extent
必须是(在我的上下文中)cudaArrayGetInfo
检索到的范围。