【问题标题】:Copy the contents of a 3D cudaArray obtained from an OpenGL texture复制从 OpenGL 纹理获得的 3D cudaArray 的内容
【发布时间】: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(&copy_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(&copy_info);

但我也收到了cudaErrorInvalidValue 的电话,cudaMemcpy3D。


我做错了什么? 当数组是来自图形 API 的纹理时,API 的限制是否禁止我调用 cudaMemcpy3D?如果是这样,我该怎么办?

【问题讨论】:

    标签: cuda textures interop


    【解决方案1】:

    经过各种测试(复制到另一个cudaArray 和其他类似的东西),问题似乎来自误解。

    文档明确指出:

    "如果一个 CUDA 数组参与复制,则范围是根据该数组的元素定义的"。

    因此,copy_info.extent 必须是(在我的上下文中)cudaArrayGetInfo 检索到的范围。

    【讨论】:

    • 我正要发布相同信息的略微 kurter 版本作为答案,但你省去了我的麻烦。感谢您回答您自己的问题。 cudaMemcy3D 是 API 的雷区,在您的用例等复杂复制情况下很容易出错。
    猜你喜欢
    • 2014-09-18
    • 2014-06-17
    • 2012-06-26
    • 2011-07-26
    • 1970-01-01
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多