Using Shared textures DX11

Started by
3 comments, last by MarcinWSB 6 years, 2 months ago

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 ?

Advertisement

The mystery is solved. The code itself is OK (option1), however I was trying to share the resource across 2 different adapters which cannot be achieved using GetSharedHandle() and needs to be done through CPU.

 

9 hours ago, MarcinWSB said:

The mystery is solved. The code itself is OK (option1), however I was trying to share the resource across 2 different adapters which cannot be achieved using GetSharedHandle() and needs to be done through CPU.

 

There is support for real cross adapter sharing without involving the cpu with D3D12 and D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER, but it is probably too much of a trouble to go that road. https://msdn.microsoft.com/en-us/library/windows/desktop/mt186623(v=vs.85).aspx

thx, indeed DX12 is not yet implemented in the game I plug into but will keep it in mind for future integrations. I guess there are not many software utilizing efficiently dual gpu capabilities .

This topic is closed to new replies.

Advertisement