c++direct3ddirect3d11direct3d9

How to create a Texture2D format YV12 (DXGI_FORMAT_420_OPAQUE)


I want create a Texture2D format DXGI_FORMAT_420_OPAQUE as input_view of VideoProcessor, then call VideoProcessorBlt convert it to RGBA format, render it in window lastly. As said in msdn,

An app using the YUY 4:2:0 formats must map the luma (Y) plane separately from the chroma (UV) planes. Developers do this by calling ID3D12Device::CreateShaderResourceView twice for the same texture and passing in 1-channel and 2-channel formats. Passing in a 1-channel format compatible with the Y plane maps only the Y plane. Passing in a 2-channel format compatible with the UV planes (together) maps only the U and V planes as a single resource view.

But i can't find example code about this method. I tried the following mehod, it failed.

D3D11 ERROR: ID3D11Device::CreateTexture2D: Initial data cannot be specified for DXGI_FORMAT_420_OPAQUE resources. [ STATE_CREATION ERROR #83: CREATETEXTURE1D_INVALIDINITIALDATA]

D3D11_TEXTURE2D_DESC desc = {0};
desc.Width = xres;
desc.Height = yres;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_420_OPAQUE;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = 0;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;

D3D11_SUBRESOURCE_DATA SubResource2D;
ZeroMemory(&SubResource2D, sizeof(SubResource2D));
SubResource2D.pSysMem = (void*)data;
SubResource2D.SysMemPitch = xres;
HRESULT hr = device->CreateTexture2D(&desc, &SubResource2D, &texture);
if (FAILED(hr))
    return false;

Then i tried UpdateSubresource method, it failed again.

D3D11 ERROR: ID3D11DeviceContext::UpdateSubresource: UpdateSubresource cannot be called on DXGI_FORMAT_420_OPAQUE. [ RESOURCE_MANIPULATION ERROR #289: UPDATESUBRESOURCE_INVALIDDESTINATIONSTATE]

ctx->UpdateSubresource(texture, 0, nullptr, data, xres, 0);

I really want to know how to use CreateShaderResourceView method to create a Texture2D and transfer YUV420p data to it, please help me out, really thanks!


Solution

  • As discussed on Microsoft Docs:

    This format differs from DXGI_FORMAT_NV12 in that the layout of the data within the resource is completely opaque to applications. Applications cannot use the CPU to map the resource and then access the data within the resource. You cannot use shaders with this format.

    If you want to manipulate it, you have to use DXGI_FORMAT_NV12.