Sign in to follow this  
Husbj

Clarifications on sharing a 2d texture between D3D9Ex and D3D11

Recommended Posts

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  :)

Edited by Husbjörn

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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. :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this