Hi,
I am trying to use shared textures with my rendering but with no success.
I create texture which I share with another process which draws on that texture. Later on I want to use that texture in my rendering loop.
//class members - once initialized, kept static during the rendering
ID3D11ShaderResourceView* g_mTexture;
ID3D11Texture2D *mTexture;
bool MyTexture::CreateTexture(ID3D11Device* device, UINT width, UINT height, int targetWidth, int targetHeight)
{
HRESULT hr;
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Width = width;
desc.Height = height;
desc.MipLevels = desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; // D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
hr = device->CreateTexture2D( &desc, NULL, &mTexture );
if (SUCCEEDED(hr))
{
D3D11_RENDER_TARGET_VIEW_DESC rtDesc;
ZeroMemory(&rtDesc, sizeof(rtDesc));
rtDesc.Format = desc.Format;
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtDesc.Texture2D.MipSlice = 0;
D3D11_SHADER_RESOURCE_VIEW_DESC svDesc;
ZeroMemory(&svDesc, sizeof(svDesc));
svDesc.Format = desc.Format;
svDesc.Texture2D.MipLevels = 1;
svDesc.Texture2D.MostDetailedMip = 0;
svDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
hr = device->CreateShaderResourceView(mTexture, &svDesc, &g_mTexture);
}
IDXGIResource * pDXGIResource;
HRESULT hr = mTexture->QueryInterface(__uuidof(IDXGIResource), (void **)&pDXGIResource);
if SUCCEEDED(hr)
{
hr = pDXGIResource->GetSharedHandle(&sharedHandle);
pDXGIResource->Release();
if SUCCEEDED(hr)
{
OutputDebug(L"RequestSharedHandle: w=%d, h=%d, handle=%d", width, height, sharedHandle);
return (unsigned long long) sharedHandle;
}
}
....
}
the problem is to use that shared handle during my rendering loop as the texture is always black, below are all the options I tried:
1) OPTION 1 (bare texture)
In this option I simply tried to use mTexture object created with device->CreateTexture2D() that I shared with another process , so basically I left my legacy code untouched with the exception of CreateTexture where I modified D3D11_TEXTURE2D_DESC options for shared version.
In my rendering loop I used g_mTexture created during init by CreateShaderResourceView
```
#!c++
pDeviceContext->PSSetShaderResources( 0, 1, &(*it_region)->g_mTexture );
```
in the legacy (without shared texture) I simply mapped the texture, copied the bits and unmapped and was working fine:
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr = pDeviceContext->Map(mTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (SUCCEEDED(hr))
{
BYTE* mappedData = reinterpret_cast<BYTE*>(mappedResource.pData);
if (mappedData != NULL) //
{
for (UINT i = 0; i < h; ++i)
{
if (bUpsideDown)
{
memcpy(mappedData, bits, w * 4);
mappedData -= mappedResource.RowPitch;
bits += (UINT)w * 4;
}
else
{
memcpy(mappedData, bits, w * 4);
mappedData += mappedResource.RowPitch;
bits += (UINT)w * 4;
}
}
}
if ((*it_region)->mTexture != NULL) pDeviceContext->Unmap(mTexture, 0);
2) OPTION 2 - OpenSharedResource
In this version I tried the get the handle to the shared texture using OpenSharedResource (with 2 combination)
// Option 2.1 - get pTexture directly
ID3D11Texture2D *pTexture; // temp handler
HRESULT hr = mDevice->OpenSharedResource(sharedHandle, __uuidof(ID3D11Texture2D), (LPVOID*)&pTexture);
// Option 2.2 get pTexture indirectly by using QueryInterface
IDXGIResource* sharedResource = 0;
HRESULT hr = mDevice->OpenSharedResource(sharedHandle, __uuidof(ID3D11Texture2D), (LPVOID*)&sharedResource);
hr = sharedResource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)(&pTexture));
OutputDebug(L"OpenSharedResource:%d\n", hr);
Now, having new temporary pTexture handle I tried the following options (with the combination of the above options retrieving the shared pTexture)
OPTION 2.3 - copy pTexure into mTexture
#!c++
mDevice->CopyResource(mTexture,pTexture);
pDeviceContext->PSSetShaderResources( 0, 1, &g_mTexture );
```
OPTION 2.4 - create new temporary shader resource using temporary pTexture
```
#!c++
ID3D11ShaderResourceView* g_pTexture; // temp handler
hr = device->CreateShaderResourceView(pTexture, &svDesc, &g_pTexture);
pDeviceContext->PSSetShaderResources( 0, 1, &g_pTexture );
```
OPTION 3 - MUTEX version
Basically I tried all above options using D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX flag during texture creation and the following code to acquire the mutex:
UINT acqKey = 1;
UINT relKey = 0;
DWORD timeOut = 5;
IDXGIKeyedMutex pMutex;
hr = pTexture->QueryInterface( __uuidof(IDXGIKeyedMutex),
(LPVOID*)&pMutex );
DWORD result = pMutex->AcquireSync(acqKey, timeOut);
if (result == WAIT_OBJECT_0)
// Rendering using 2.2 and 2.3 options ....
else
// nothing here - skip frame
result = pMutex->ReleaseSync(relKey));
if ( result == WAIT_OBJECT_0 )
return S_OK;
NONE of those solutions worked for me, any HINTS ?