【问题标题】:Direct write to D3D texture from kernel从内核直接写入 D3D 纹理
【发布时间】:2021-06-09 18:19:17
【问题描述】:

我正在使用来自 NVIDIA CUDA 样本的 NVDEC H.264 解码器,我发现一件事是一旦帧被解码,它就会从 NV12 转换为分配在 CUDA 端的 BGRA 缓冲区,然后复制这个缓冲区到 D3D BGRA 纹理。

我发现这在内存使用方面效率不高,并希望使用此内核将 NV12 帧直接转换为 D3D 纹理:

void Nv12ToBgra32(uint8_t *dpNv12, int nNv12Pitch, uint8_t *dpBgra, int nBgraPitch, int nWidth, int nHeight, int iMatrix)

因此,创建 D3D 纹理(BGRA、D3D11_USAGE_DEFAULT、D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS、D3D11_CPU_ACCESS_WRITE、1 个 mipmap), 然后注册并写在CUDA端:

//Register
ck(cuGraphicsD3D11RegisterResource(&cuTexResource, textureResource, CU_GRAPHICS_REGISTER_FLAGS_NONE));

...
//Write output:
CUarray retArray;
ck(cuGraphicsMapResources(1, &cuTexResource, 0));
ck(cuGraphicsSubResourceGetMappedArray(&retArray, cuTexResource, 0, 0));

/*
yuvFramePtr (NV12) is uint8_t* from decoded frame,
it's stored within CUDA memory I believe
*/

Nv12ToBgra32(yuvFramePtr, w, (uint8_t*)retArray, 4 * w, w, h);

ck(cuGraphicsUnmapResources(1, &cuTexResource, 0));

一旦调用内核,我就会崩溃。可能是因为滥用 CUarray,有人可以澄清如何使用 cuGraphicsSubResourceGetMappedArray 的输出从 CUDA 内核写入纹理内存吗? (由于只需要写入原始内存,因此无需处理正确的钳位、过滤和值缩放)

【问题讨论】:

    标签: c++ cuda direct3d nvdec cuda-arrays


    【解决方案1】:

    好的,对于那些在“如何从 CUDA 内核编写 D3D11 纹理”问题上苦苦挣扎的人来说,方法如下:

    使用 D3D11_BIND_UNORDERED_ACCESS 创建 D3D 纹理。 然后,注册资源:

    //ID3D11Texture2D *textureResource from D3D texture
    CUgraphicsResource cuTexResource;
    ck(cuGraphicsD3D11RegisterResource(&cuTexResource, textureResource, CU_GRAPHICS_REGISTER_FLAGS_NONE));
    
    //You can also add write-discard if texture will be fully written by kernel
    ck(cuGraphicsResourceSetMapFlags(cuTexResource, CU_GRAPHICS_MAP_RESOURCE_FLAGS_WRITE_DISCARD));
    

    创建并注册纹理后,我们可以将其用作写入表面。

    ck(cuGraphicsMapResources(1, &cuTexResource, 0));
    
    //Get array for first mip-map
    CUArray retArray;
    ck(cuGraphicsSubResourceGetMappedArray(&retArray, cuTexResource, 0, 0));
    
    //Create surface from texture
    CUsurfObject surf;
    CUDA_RESOURCE_DESC surfDesc{};
    surfDesc.res.array.hArray = retArray;
    surfDesc.resType = CU_RESOURCE_TYPE_ARRAY;
    ck(cuSurfObjectCreate(&surf, &surfDesc));
    
    /* 
    Kernel declaration is:
    void Nv12ToBgra32Surf(uint8_t* dpNv12, int nNv12Pitch, cudaSurfaceObject_t surf, int nBgraPitch, int nWidth, int nHeight, int iMatrix)
    
    Surface write:
    surf2Dwrite<uint>(VALUE, surf, x * sizeof(uint), y);
    For BGRA surface we are writing uint, X offset is in bytes,
    so multiply it with byte-size of type.
    
    Run kernel:
    */
    Nv12ToBgra32Surf(yuvFramePtr, w, /*out*/surf, 4 * w, w, h);
    
    ck(cuGraphicsUnmapResources(1, &cuTexResource, 0));
    ck(cuSurfObjectDestroy(surf));
    

    【讨论】:

      猜你喜欢
      • 2011-12-03
      • 2023-01-02
      • 2021-07-20
      • 2013-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-22
      • 2015-10-24
      相关资源
      最近更新 更多