[Feature request] Implement D3D11-OpenCL interop/sharing (cl_khr_d3d11_sharing)
Don't know if this is the right place to ask, but what would it require to implement D3D11/OpenCL sharing using the cl_khr_d3d11_sharing OpenCL extension? Is it even possible/feasible to do?
What's the use case here exactly?
Interop with external APIs generally would need to be implemented on top of the existing Vulkan resource sharing (and outside of DXVK, literally nothing we do inside d3d11.dll alone has any impact on what OpenCL apps can or can't see), but I don't know how feasible this is given that we can only really support basic 2D images as shared resources.
I'm working on a Windows app which internally uses DX/CL sharing extensively, and I'm investigating the possibility of getting it to run under WINE. Sharing images should be sufficient.
I found this: https://docs.vulkan.org/samples/latest/samples/extensions/open_cl_interop/README.html So basically it needs the VK_KHR_external_memory and cl_khr_external_memory extensions to work, and some setup on the Vulkan side when creating the image. Taking a quick look in the dxvk sources, it looks like this is already done when D3D11_RESOURCE_MISC_SHARED is specified for a texture. To be able to make a proof-of-concept for this, is it possible for an app to get the internals of a dxvk d3d11 texture, ie. the underlying VkImage?
Looking a bit more, is IDXGIVkInteropSurface would be the appropriate interface to achieve this?
Yes, that's the interface to use on images created via D3D. There's also IDXGIVkInteropDevice1 to import existing Vulkan resources.
That said, to temper some expectations, CL is rather dodgy on Linux, and CL <-> VK interop probably just isn't supported on wine either so there would be a ton of work involved either way.
OK, thanks for the heads up. Looks like you are right, the mechanism to get OpenCL extension pointers are not implemented in WINE at all, and to make this work at all I'd need to be able to call clEnqueueAcquireExternalMemObjectsKHR / clEnqueueReleaseExternalMemObjectsKHR. One workaround, without implementing this in WINE itself, is to write a proxy DLL using winelib which would make the necessary calls. Sounds hacky, but should be doable.
Anyway, thanks for the help, I'll update this issue with the progress, if I get to it...
Is there any way with which I can get the VkDeviceMemory associated with a (shared) D3D11 Texture? IDXGIVkInteropSurface::GetVulkanImageInfo() doesn't provide that information.
There's currently no api for that. Shouldn't be too hard to hack in based on the existing functionality since shared images are never relocated to different memory, but I'm hesitant to upstream interop features when it's not clear yet that any of this is even going to work at all.
Thanks. Sure, the proof of concept I'm doing already needs using some WINE internal data structures to get the host-side vulkan handles, rather than the wrapped client-side ones, which is easy enough to do, but not official either.
I was just curious if there's any API with which I could get this info, before I attempt to fork and hack DXVK to get this, along with compiling it, but it looks like I can't avoid that at this point.
Just to verify, I basically need to expose DxvkImage::getMemoryInfo(), that should give me what I need, correct?
I seem to be hitting a brick wall that I cannot wrap my head around.
For starters, I added the GetMemoryInfo() to DXVK, and it works fine, so I can get the VkDeviceMemory for a d3d11 texture, but that is not the main issue.
Basically what I'm doing is that I wrote a separate DLL/SO using winegcc, which exports a few functions for the Windows EXE to call. That works fine, I can call into this SO from the EXE through GetProcAddress()-ed functions. The idea is that I'd pass the obtained VkInstance, VkDeviceMemory, etc handles over to this .SO, and it would in turn make the necessary calls directly into libvulkan.so to obtain a file descriptor (which is necessary to later on pass to OpenCL).
Now, I know that the WINE vulkan layer wraps the host-side vulkan handles using vulkan_object and vulkan_client_object structs to hide the internal VkInstance it got from libvulkan.so. So I do the same thing, I unwrap the VkInstance I got from the Windows EXE to get to the "host-side" VkInstance, and I verified that it's correct by looking at the second uint64 value of the pointed address, and indeed it shows 0x10ADED010110ADED, which is exactly what the Vulkan-Loader puts there (from Vulkan-Loader/loader/loader-common.h: #define LOADER_MAGIC_NUMBER 0x10ADED010110ADEDUL).
But as soon as I attempt to call vkGetInstanceProcAddr() (which I dlsym()-ed from libvulkan.so) from inside the .SO which I built with winegcc, it just refuses the handle, printing to the console ... Invalid instance [VUID-vkGetInstanceProcAdd-instance-parameter]
In fact, if I call vkGetInstanceProcAddr(NULL, "vkGetInstanceProcAddr") just as a basic test, it outright crashes, which makes no sense, as it should just give back it's own pointer in this dummy test.
So long story short, either my approach is dead-on-arrival for some reason that I'm completely unaware of, or I'm missing some crucial detail.
I know that this is not the right place to ask this, but perhaps someone with deep knowledge about WINE might be able to explain what's going on here.
Thank you.