DirectX 11 - Vulkan interoperability

I am following up my previous post here. I managed to share an image between two applications.

Now I would like to provide interoperability between DirectX and Vulkan. In particular, I am trying to transfer a render target from an application (provided as an ID3D11RenderTargetView interface, from which I can derive an ID3D11Resource) to another application using Vulkan external memory. Which DirectX data/object should I get to transfer to Vulkan? Is it possible to get a handle on the GPU from DirectX and transfer it to Vulkan? Or can I simply pass the ID3D11RenderTargetView object?

A related question, is this process possible without any data copy from GPU to CPU? (How do I check that?)

Many thanks,
Nicholas

You get a HANDLE via CreateSharedHandle from ID3D*Resource. Then you make import vkAllocateMemory using that HANDLE. Plus all the boilerplate inbetween the DX and Vk requires…

Thank you @krOoze.

Sorry if the next thing is out of the scope of the forum. I have progressed a little bit and now I can create an IDXGIResource1. I am then trying to get a HANDLE from CreateSharedHandle with this code.

HANDLE sharedHandle;
HRESULT hresult2 = dxgiResource->CreateSharedHandle(NULL,
    DXGI_SHARED_RESOURCE_READ,
    NULL,
    &sharedHandle);

However, the handle remains null, with an E_INVALIDARG return value. Do you know what the problem is? Is that because the resource is not a shared resource? (I am getting it from an external application, which means it is beyond my control)

EDIT: I am now trying to create a copy resource using
ID3D11DeviceContext::CopyResource, and it seems I can export the texture. However, I am getting an VK_ERROR_INVALID_EXTERNAL_HANDLE when running vkAllocateMemory. Perhaps I am not setting the right configuration.

I am also wondering if there is an alternative method without doing the copy resource step.

Well yea, the resource must be created as SHARED_NTHANDLE.

If you need to copy, it might make sense to do it the other way and export a Vulkan image.

Hi krOoze,

Sorry I have just returned to this problem. At the moment I can get an NT handle from the copied DX 11 texture using the following description.

D3D11_TEXTURE2D_DESC dxDestinationResourceDesc = dxSrcResourceDesc;
dxDestinationResourceDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
dxDestinationResourceDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_NTHANDLE | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;

Is it possible to tell if the handle is a GPU handle (e.g. 0x000000000000157c)?

I pass this handle into a VkImportMemoryWin32HandleInfoKHR, which is eventually added to the pNext chain of VkMemoryAllocateInfo, and used as a parameter to vkAllocateMemory. I am now getting VK_ERROR_OUT_OF_DEVICE_MEMORY. Do you know what the problem is?

Another related question: is it possible to access the shared memory by the name? The IDXGIResource1::CreateSharedHandle method has an lpName variable. I was wondering if the same string can be used to access the same memory in Vulkan? I tried to pass the name instead of the handle, and I am getting an VK_ERROR_INVALID_EXTERNAL_HANDLE (as per my previous post).

Regarding your previous comment: how do I create a Vulkan texture from a DX11 texture? Is it possible to do it without copying the texture to the CPU memory?

Is it possible to tell if the handle is a GPU handle (e.g. 0x000000000000157c)?

Sorta. You should get a VK_ERROR_INVALID_EXTERNAL_HANDLE otherwise.
Of course you should know if it is, because you need to create it and you need to match the GUIDs (or LUIDs) of the GPU across the APIs.
Or maybe trying to re-import it in DX would fail with some HRESULT.

I am now getting VK_ERROR_OUT_OF_DEVICE_MEMORY . Do you know what the problem is?

Nope.
I think it might be if you do not check if it needs a Dedicated Allocation.
On AMD I had problems with a bug that it does not properly report in queries. Write a magic value to a query parameter, and check afterwards if the driver actually modifies the value.
Otherwise just go over the Valid Usage section like a checklist.

I was wondering if the same string can be used to access the same memory in Vulkan?

Well yea, I would assume that is what the parameter does.

Regarding your previous comment: how do I create a Vulkan texture from a DX11 texture?

You mean how to create DX11 texture from Vulkan Image?

If you are gonna copy anyway, it feels more natural this direction.
vkCreateImage as you would normally do. Use VkExportMemoryWin32HandleInfoKHR on vkAllocateMemory. Then vkGetMemoryWin32HandleKHR to get HANDLE. Then OpenSharedResource on DX and copy into it.

Is it possible to do it without copying the texture to the CPU memory?

That’s what the extension is for. The assumption is import\export is 0-copy; just a type cast.

PS: Here’s some of my Import code for reference: https://github.com/krOoze/Hello_Triangle/blob/dxgi_interop/src/WSI/DxgiWsi.h

I am hijacking DXGI swapchain, and using D3D12, but it should be only trivially different and all the boilerplate is there.

Thanks for your code! I am trying to understand it now (as well as a few other concepts you mentioned). After checking the DeviceID, I can see that the device that I am accessing from both DX 11 and Vulkan is the same.

You mean how to create DX11 texture from Vulkan Image?

No, from DX11 to Vulkan. I am trying to make a plugin to access the DX11 render target created by an external application, then either:

  1. (Preferrably) save the image to the shared memory using DX11’s shared handle, or:
  2. Create a Vulkan texture and use Vulkan to save it to the shared memory.

Another application (which I create) will finally access the shared memory using Vulkan, preferrably using the name (string) as the identifier, instead of the handle. I have previously been successful in sending an image, created from Vulkan in one application, to another application, also using Vulkan (referring to my previous thread).