Clarifications on sharing a 2d texture between D3D9Ex and D3D11

Started by
3 comments, last by Husbj 7 years, 7 months ago

I'm trying to set up a shared texture (render target) such that it is created on a D3D11 device and subsequently opened and drawn to from a D3D9Ex device. Unfortunately I've found the information on how to actually go about this to be rather scarce and the debug layers don't seem to want to be more helpful than to tell me the "opened and created resources don't match". Therefore I thought I would ask and see if anybody around here would be able and willing to shed some more light on how resource sharing is supposed to be carried out?

So what I do is to first create a Texture2D from my IDirect3D11Device like so:


tex2DDesc.Width					= width;		// Tested with 256
tex2DDesc.Height				= height;		// Tested with 256
tex2DDesc.MipLevels				= 1;
tex2DDesc.ArraySize				= 1;
tex2DDesc.Format				= DXGI_FORMAT_A8G8B8R8_UNORM;
tex2DDesc.SampleDesc.Count			= 1;
tex2DDesc.SampleDesc.Quality		        = 0;
tex2DDesc.Usage					= D3D11_USAGE_DEFAULT;
tex2DDesc.BindFlags				= D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
tex2DDesc.CPUAccessFlags			= 0;
tex2DDesc.MiscFlags				= D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;

// Create render target
if(FAILED(gGlob.pDevice->CreateTexture2D(&tex2DDesc, nullptr, &pTexture2D)))
	Fail("Failed to create shared texture", "Could not create the shared texture!", 1);

// Create shader resource view
srvDesc.ViewDimension				= D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Format					= DXGI_FORMAT_A8G8B8R8_UNORM;
srvDesc.Texture2D.MipLevels			= 1;
srvDesc.Texture2D.MostDetailedMip	        = 0;
if(FAILED(gGlob.pDevice->CreateShaderResourceView(pTexture2D, &srvDesc, &pResourceView)))
        Fail("Failed to create shared texture", "Could not create SRV for shared texture!", 2);

// Obtain the keyed mutex interface
if(FAILED(pTexture2D->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)&pMutex)))
	Fail("Failed to create shared texture", "Could not obtain resource locking interface!", 3);

// Obtain IDXGIResource interface for the texture; this is needed to get its shared handle
IDXGIResource *pResource = nullptr;
if(FAILED(pTexture2D->QueryInterface(__uuidof(IDXGIResource), (void**)&pResource)))
	Fail("Failed to create shared texture", "Could not obtain resource interface!", 4);
if(FAILED(pResource->GetSharedHandle(&hSharedResource)))
	Fail("Failed to create shared texture", "Could not obtain shared resource handle!", 5);
// Shouldn't need this open anymore; the handle should presumably be valid for as long as the 
// resource (the texture2d) remains in existance
SAFE_RELEASE(pResource);

After this, an attempt is made to access it from an IDirect3DDevice9Ex:


hr = m_pD3DEx->CreateTexture(iWidth, iHeight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pTexture, &hSharedResource);
// The above returns E_INVALIDARG

The D3D9 debug layer reports the following when invoking CreateTexture as per above:


Direct3D9: (ERROR) :Opened and created resources don't match, unable to open the shared resource.
Direct3D9: (ERROR) :Error during initialization of texture. CreateTexture failed.
Direct3D9: (ERROR) :Failure trying to create a texture

The D3D11 debug layer remains silent and all D3D11 calls above succeed.

From what I've been able to gather while searching for info on this, this seems to be how you are supposed to set it up. Most places that mention it seem to make a point of having D3D9Ex create the resource and then open it using ID3D11Device::OpenSharedResource however. But certainly this can't be a requirement? In my project it makes a whole lot better sense to have the D3D11 device create the shared textures than the other way around.

Furthermore there is the slightly ambigious route of getting the IDXGIResource interface from the IDXGITexture2d in order to obtain the shared handle. Could it be that you are in fact supposed to get this from somewhere else? The MSDN documentation seems prone to refer to surfaces when talking about resource sharing; is it in fact supposed to be so that you are supposed to be sharing the IDXGISurface view of the resource? But while D3D9 uses surfaces, what would the corresponding thing be in D3D11 if so, since it is apparently imperative that both resources be created / opened using the same type? (Furthermore it appears that texture resources should indeed be shareable out-of-the-box going by some mentions here: https://msdn.microsoft.com/en-us/library/windows/desktop/bb219800(v=vs.85).aspx#Sharing_Resources).

Grateful for any pointers :)

Advertisement
What is DXGI_FORMAT_A8G8B8R8_UNORM? As far as I can tell, it does not exist. The D3D11 equivalent of D3DFMT_A8R8G8B8 is DXGI_FORMAT_B8G8R8A8_UNORM.

What is DXGI_FORMAT_A8G8B8R8_UNORM? As far as I can tell, it does not exist. The D3D11 equivalent of D3DFMT_A8R8G8B8 is DXGI_FORMAT_B8G8R8A8_UNORM.

Ah that's a typo haha.

I cut the relevant part out of a function, it was originally an argument identifier, so I thought I'd replace it with DXGI_FORMAT_B8G8R8A8_UNORM (which is indeed what it should have been) for clarity.

D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
is not understood by D3D9. There is no IDirect3D9KeyedMutex interface (or anything like it) with which to synchronize on the 9 side.

The documentation you're looking for, as well as a sample (found a copy of what was once behind the dead link on the doc page).

I see... indeed, IDXGIKeyedMutex snuck into my D3D9 project through the Windows 7 API rather than D3D9 itself, leading me to assume it was available.

Thanks for pointing that out, as well as the links! Now all that is left is to wait for the next weekend so that I can dig into it. :)

This topic is closed to new replies.

Advertisement