DirectX 11 Shared Texture Lock

Shared texture usage scenarios:
When the hard decoded texture is passed across two device objects (corresponding to a graphics card), such as decoding device1 and rendering device2, it is necessary to first copy the decoded texture to the shared texture through the shared texture, then obtain the texture handle and pass it to the shaded device2. The rendered device2 can open this handle to obtain a texture for sampling and rendering
If not locked, there will be tearing when drawing high-resolution videos or outputting high-resolution images.

The specific steps are as follows:

1. Obtain the decoded texture.

ID3D11VideoDecoderOutputView* srcSurface = (ID3D11VideoDecoderOutputView*)(uintptr_t)frame->m_frame->data[3];
D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc;
srcSurface->GetDesc(&viewDesc);
int slice = viewDesc.Texture2D.ArraySlice;
ComPtr<ID3D11Texture2D> srcTexture;
srcSurface->GetResource((ID3D11Resource**)srcTexture.GetAddressOf());

2. Create shared textures.

D3D11_TEXTURE2D_DESC dstTexDesc;
ZeroMemory(&dstTexDesc, sizeof(dstTexDesc));
dstTexDesc.Width = frame->getWidth();
dstTexDesc.Height = frame->getHeight();
dstTexDesc.MipLevels = 1;
dstTexDesc.ArraySize = 1;
dstTexDesc.Format = DXGI_FORMAT_NV12;
dstTexDesc.SampleDesc.Count = 1;
dstTexDesc.Usage = D3D11_USAGE_DEFAULT;
dstTexDesc.BindFlags =  D3D11_BIND_SHADER_RESOURCE| D3D11_BIND_RENDER_TARGET;
dstTexDesc.CPUAccessFlags = 0;
dstTexDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; //shared texture with lock attention :D3D11_RESOURCE_MISC_SHARED_NTHANDLE this symbol may cause damage to the vase, use with caution 
//dstTexDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
HRESULT hr = m_device->CreateTexture2D(&dstTexDesc, nullptr, m_sharedTexture_HW.ReleaseAndGetAddressOf());

3. Obtain shared texture handles and locks.

//obtain texture lock 
m_sharedTexture_HW.As(&m_sharedkeyMutex0);
//get handle to texture 
ComPtr<IDXGIResource1> sharedResource = nullptr;
m_sharedTexture_HW->QueryInterface(__uuidof(IDXGIResource1), reinterpret_cast<void**>(sharedResource.ReleaseAndGetAddressOf()));
//D3D11_RESOURCE_MISC_SHARED_NTHANDLE this flag obtains a texture handle using the following method 
//sharedResource->CreateSharedHandle(nullptr, DXGI_SHARED_RESOURCE_READ, nullptr, &m_sharedHandle0_SW);
sharedResource->GetSharedHandle(&m_sharedHandle_HW);
sharedResource.Reset();

5. Lock when updating textures.

//blt convert to update texture 
m_sharedkeyMutex0->AcquireSync(0, INFINITE);
bool processFlag = m_d3d11VideoPorcessor->process(srcTexture.Get(), viewDesc.Texture2D.ArraySlice);
m_sharedkeyMutex0->ReleaseSync(0);
//another type copy method of updating texture 
m_sharedkeyMutex0->AcquireSync(0, INFINITE);
m_pd3dDeviceContext->CopySubresourceRegion( m_sharedTexture_HW.Get(), 0, 0, 0, 0, srcTexture.Get(), slice, nullptr);
m_sharedkeyMutex0->ReleaseSync(0);

6. The rendering device opens a shared texture handle.

ComPtr<ID3D11Texture2D> pTexture0;
ComPtr<IDXGIKeyedMutex> sharedkeyMutex;
HRESULT hr = m_pd3dDevice->OpenSharedResource(m_sharedHandle_HW, __uuidof(ID3D11Texture2D), (void**)(&pTexture0));
pTexture0.As(&sharedkeyMutex);

7. Lock before drawing and unlock after drawing.

 sharedkeyMutex->AcquireSync(0, INFINITE);
deviceContext->DrawIndexed(m_IndexCount, 0, 0);
sharedkeyMutex->ReleaseSync(0);