Problem Exporting Vulkan Image to Direct3D 11 via shared handle

Hi,

I’m currently trying to understand the usage of the VK_KHR_external_memory (and _win32) extension in the context of sharing a Vulkan created texture (image) with a Direct3D 11.1 device (created using the same GPU as the Vulkan device, LUIDs do match).

I have a hard time finding documentation or examples about this. The main problem I have is that exceptions are triggered when trying to open the handle I get with D3D11Device1::OpenSharedResource1(). Even with DirectX debug layers on, I only get a rather unhelpful long at memory location error in the log.

I am at the point where I have a VkImage created, and the underlying VkDeviceMemory allocated with the relevant structure passed for exporting a win32 handle.

format is R8G8B8A8_UNORM and handleType is set to VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR :

		VkExternalMemoryImageCreateInfoKHR externalMemoryImageCreateInfo
		{
			VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
			nullptr,
			handleType 
		};

		VkImageCreateInfo imageCreateInfo{ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, &externalMemoryImageCreateInfo };
		imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
		imageCreateInfo.extent.width = texture.getWidth();
		imageCreateInfo.extent.height = texture.getHeight();
		imageCreateInfo.extent.depth = 1;
		imageCreateInfo.mipLevels = 1;
		imageCreateInfo.arrayLayers = 1;
		imageCreateInfo.format = imageFormat;
		imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
		imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
		imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
		imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
		imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
		imageCreateInfo.flags = 0;

		vkCreateImage(device, &imageCreateInfo, nullptr, &textureImage);
		VkMemoryRequirements imageMemoryRequirement{};
		vkGetImageMemoryRequirements(device, textureImage, &imageMemoryRequirement);

		VkExportMemoryWin32HandleInfoKHR exportMemoryWin32HandleInfo
		{ VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
			nullptr,
			nullptr,
			DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE ,
			nullptr
		};

		VkExportMemoryAllocateInfo exportMemoryAllocateInfo
		{
			VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
			&exportMemoryWin32HandleInfo,
			handleType 
		};

		VkMemoryAllocateInfo imageAllocateInfo
		{
			VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
			&exportMemoryAllocateInfo,
			imageMemoryRequirement.size,
			deviceLocalMemoryIndex.front() //1st in this array is dedicated GPU memory
		};

		vkAllocateMemory(device, &imageAllocateInfo, nullptr, &imageDeviceMemory);
		vkBindImageMemory(device, textureImage, imageDeviceMemory, 0);


		transitionImageLayout(textureImage, imageFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
		copyBufferToImage(textureDataBufferUpload, textureImage, static_cast<uint32_t>(texture.getWidth()), static_cast<uint32_t>(texture.getHeight()));

I can obtain a HANDLE that way:

		VkMemoryGetWin32HandleInfoKHR getWin32HandleInfo{ VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR, nullptr };
		getWin32HandleInfo.memory = imageDeviceMemory;
		getWin32HandleInfo.handleType = handleType;
		HANDLE output = INVALID_HANDLE_VALUE;
		vkGetMemoryWin32HandleKHR(device, &getWin32HandleInfo, &output);

After this, the image is in “transfer optimal layout”, and I do not know if this is important for the resource sharing between the 2 APIs. I attempted to transition the image in the general layout, with the memory read/write access mask, and to the “all commands” pipeline stage, but I have the same problem.

This passes all Vulkan validations. I am clueless about what I am doing wrong. The texture is being created properly on the Vulkan side (I think), as it is readable in a GPU debugger like Nsight and displays the expected content.

Edit: Code that attempt to open handle, and fails:

			ID3D11Texture2D* textureFromVulkanResource = nullptr;
			const auto openShareResult = D3D11Device1->OpenSharedResource1(shareHandle, __uuidof(ID3D11Texture2D), (void**)&textureFromVulkanResource);