Прямая запись в текстуру D3D из ядра

Я играю с декодером NVDEC H.264 из образцов NVIDIA CUDA, одна вещь, которую я обнаружил, - это когда кадр декодируется, он конвертируется из NV12 в буфер BGRA, который выделяется на стороне CUDA, затем этот буфер копируется в 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? (поскольку требуется только запись необработанной памяти, нет необходимости обрабатывать правильное ограничение, фильтрацию и масштабирование значений)

1 ответ

Хорошо, для тех, кто борется с вопросом «Как написать текстуру D3D11 из ядра CUDA», вот как:

Создайте текстуру D3D с помощью D3D11_BIND_UNORDERED_ACCESS. Затем зарегистрируйте ресурс:

      //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));
Другие вопросы по тегам