- Notifications
You must be signed in to change notification settings - Fork0
How to render into DirectX context using Vulkan
License
jack-day/vulkan-interop-directx
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
This repo demonstrates interop between Vulkan and DirectX via embedding the former into WinUI 3 and WPF usingVK_KHR_external_memory_win32 extension. It's basically follows greatAlexander Overvoorde's tutorial for creating resources, but excludes swapchain infrastructure and creates a framebuffer using a shared Direct3D 11 texture.
Whether you are using your own or third party abstractions - it should be easy to adapt the code for use.
The example is written naively, step by step - seeVulkanInterop.Initialize andWindow code behind.
Silk.NET - bindings used for DirectX and Vulkan calls.
Damaged Helmet - model used as an example.SharpGLTF - loader used to read the model.
vulkan-interop-directx.mp4
We need to
In case of WinUI - create a DXGI swapchain, get the texture and set the swapchain to the WinUI SwapChainPanel.
varswapchainDescription=newSwapChainDesc1{ ...Width=width,Height=height,Format=Format.FormatR8G8B8A8Unorm,SwapEffect=SwapEffect.FlipSequential,SampleDesc=newSampleDesc(1u,0u),BufferUsage=DXGI.UsageBackBuffer};ThrowHResult(dxgiFactory.CreateSwapChainForComposition(dxgiDevice,swapchainDescription,default(ComPtr<IDXGIOutput>),refswapchain));backbufferTexture=swapchain.GetBuffer<ID3D11Texture2D>(0u);target.As<ISwapChainPanelNative>().SetSwapChain(swapchain);
In case of WPF - create a D3D9 texture and get the surface that will be used with WPF D3DImage.
void*d3d9shared=null;ThrowHResult(d3d9device.CreateTexture(width,height,1u,D3D9.UsageRendertarget,Silk.NET.Direct3D9.Format.X8R8G8B8,Pool.Default,refbackbufferTexture,refd3d9shared));ThrowHResult(backbufferTexture.GetSurfaceLevel(0u,refsurface));
In case of WinUI - this is regular D3D11 texture.
varrenderTargetDescription=newTexture2DDesc{ ...Width=width,Height=height,BindFlags=(uint)BindFlag.RenderTarget,MiscFlags=(uint)ResourceMiscFlag.Shared};ThrowHResult(d3d11device.CreateTexture2D(renderTargetDescription,null,refrenderTargetTexture));
With WinUI we also need to query both back buffer and render target textures to D3D11 resources for future copy operations.
backbufferResource=backbufferTexture.QueryInterface<ID3D11Resource>();renderTargetResource=renderTargetTexture.QueryInterface<ID3D11Resource>();
In case of WPF, we get the texture using shared handle of the D3D9 texture we created earlier.
renderTargetTexture=d3d11device.OpenSharedResource<ID3D11Texture2D>(d3d9shared);
void*handle;varresource=renderTargetTexture.QueryInterface<IDXGIResource>();ThrowHResult(resource.GetSharedHandle(&handle));resource.Dispose();renderTargetSharedHandle=(nint)handle;
Then create the view and framebuffer - seeVulkanInterop.CreateImageViews.
varexternalMemoryImageInfo=newExternalMemoryImageCreateInfo(handleTypes:ExternalMemoryHandleTypeFlags.D3D11TextureKmtBit);varimageInfo=newImageCreateInfo( ...format: targetFormat,usage:ImageUsageFlags.ColorAttachmentBit,pNext:&externalMemoryImageInfo);varimportMemoryInfo=newImportMemoryWin32HandleInfoKHR(handleType:ExternalMemoryHandleTypeFlags.D3D11TextureKmtBit,handle:renderTargetSharedHandle);vk.CreateImage(device,imageInfo,null,outdirectImage).Check();
Note that D3D9
X8R8G8B8
texture format map to VulkanB8G8R8A8Unorm
With WinUI we need to call Direct3D 11 to copy data from the render target to the back buffer and present it.
// *rendering*d3d11context.CopyResource(backbufferResource,renderTargetResource);ThrowHResult(swapchain.Present(0u,(uint)SwapChainFlag.None));
With WPF we only need to set the D3D9 surface to the D3DImage, because the back buffer already contains the rendered image.
d3dImage.Lock();// *rendering*d3dImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9,(nint)d3d9surface.Handle);d3dImage.AddDirtyRect(newInt32Rect(0,0,d3dImage.PixelWidth,d3dImage.PixelHeight));d3dImage.Unlock();
- .NET 8
- Windows SDK 10.0.22621
The example isdotnet build
ready.