Browse Source

Merge pull request #10333 from AvaloniaUI/feature/use-nt-shared-handles

Use NT shared handles for Vulkan interop on Windows
Max Katz 2 years ago
parent
commit
953177d937

+ 1 - 1
samples/GpuInterop/VulkanDemo/D3DMemoryHelper.cs

@@ -47,7 +47,7 @@ public class D3DMemoryHelper
                 MipLevels = 1,
                 SampleDescription = new SampleDescription { Count = 1, Quality = 0 },
                 CpuAccessFlags = default,
-                OptionFlags = ResourceOptionFlags.SharedKeyedmutex,
+                OptionFlags = ResourceOptionFlags.SharedKeyedmutex|ResourceOptionFlags.SharedNthandle,
                 BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource
             });
     }

+ 1 - 1
samples/GpuInterop/VulkanDemo/VulkanContext.cs

@@ -173,7 +173,7 @@ public unsafe class VulkanContext : IDisposable
                 api.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, ref queueFamilyCount, familyProperties);
                 for (uint queueFamilyIndex = 0; queueFamilyIndex < queueFamilyCount; queueFamilyIndex++)
                 {
-                    var family = familyProperties[c];
+                    var family = familyProperties[queueFamilyIndex];
                     if (!family.QueueFlags.HasAllFlags(QueueFlags.GraphicsBit))
                         continue;
 

+ 21 - 11
samples/GpuInterop/VulkanDemo/VulkanImage.cs

@@ -4,10 +4,13 @@ using System.Runtime.InteropServices;
 using Avalonia;
 using Avalonia.Platform;
 using Avalonia.Vulkan;
+using SharpDX.DXGI;
 using Silk.NET.Vulkan;
 using Silk.NET.Vulkan.Extensions.KHR;
 using SilkNetDemo;
 using SkiaSharp;
+using Device = Silk.NET.Vulkan.Device;
+using Format = Silk.NET.Vulkan.Format;
 
 namespace GpuInterop.VulkanDemo;
 
@@ -24,7 +27,6 @@ public unsafe class VulkanImage : IDisposable
         private ImageView? _imageView { get; set; }
         private DeviceMemory _imageMemory { get; set; }
         private SharpDX.Direct3D11.Texture2D? _d3dTexture2D;
-        private IntPtr _win32ShareHandle;
         
         internal Image? InternalHandle { get; private set; }
         internal Format Format { get; }
@@ -60,7 +62,7 @@ public unsafe class VulkanImage : IDisposable
             //MipLevels = MipLevels != 0 ? MipLevels : (uint)Math.Floor(Math.Log(Math.Max(Size.Width, Size.Height), 2));
 
             var handleType = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
-                ExternalMemoryHandleTypeFlags.D3D11TextureKmtBit :
+                ExternalMemoryHandleTypeFlags.D3D11TextureBit :
                 ExternalMemoryHandleTypeFlags.OpaqueFDBit;
             var externalMemoryCreateInfo = new ExternalMemoryImageCreateInfo
             {
@@ -108,14 +110,14 @@ public unsafe class VulkanImage : IDisposable
             if (exportable && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
             {
                  _d3dTexture2D = D3DMemoryHelper.CreateMemoryHandle(vk.D3DDevice, size, Format);
-                 using var dxgi = _d3dTexture2D.QueryInterface<SharpDX.DXGI.Resource>();
-                 _win32ShareHandle = dxgi.SharedHandle;
+                 using var dxgi = _d3dTexture2D.QueryInterface<SharpDX.DXGI.Resource1>();
+                 
                  handleImport = new ImportMemoryWin32HandleInfoKHR
                  {
                      PNext = &dedicatedAllocation,
                      SType = StructureType.ImportMemoryWin32HandleInfoKhr,
-                     HandleType = ExternalMemoryHandleTypeFlags.D3D11TextureKmtBit,
-                     Handle = _win32ShareHandle,
+                     HandleType = ExternalMemoryHandleTypeFlags.D3D11TextureBit,
+                     Handle = dxgi.CreateSharedHandle(null, SharedResourceFlags.Read | SharedResourceFlags.Write),
                  };
             }
 
@@ -185,11 +187,19 @@ public unsafe class VulkanImage : IDisposable
             return fd;
         }
         
-        public IPlatformHandle Export() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
-            new PlatformHandle(_win32ShareHandle,
-                KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle) :
-            new PlatformHandle(new IntPtr(ExportFd()),
-                KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaquePosixFileDescriptor);
+        public IPlatformHandle Export()
+        {
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            {
+                using var dxgi = _d3dTexture2D!.QueryInterface<Resource1>();
+                return new PlatformHandle(
+                    dxgi.CreateSharedHandle(null, SharedResourceFlags.Read | SharedResourceFlags.Write),
+                    KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureNtHandle);
+            }
+            else
+                return new PlatformHandle(new IntPtr(ExportFd()),
+                    KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaquePosixFileDescriptor);
+        }
 
         public ImageTiling Tiling => ImageTiling.Optimal;
 

+ 40 - 0
src/Windows/Avalonia.Win32/DirectX/directx.idl

@@ -36,6 +36,8 @@
 @clr-map DXGI_SHARED_RESOURCE void*
 @clr-map LUID ulong
 @clr-map LPSTR ushort*
+@clr-map LPWSTR ushort*
+@clr-map LPCWSTR ushort*
 
 
 enum DXGI_FORMAT
@@ -501,6 +503,44 @@ interface ID3D11Device : IUnknown
     UINT GetExceptionMode();
 }
 
+[uuid(a04bfb29-08ef-43d6-a49c-a9bdbdcbe686)]
+interface ID3D11Device1 : ID3D11Device
+{
+    void GetImmediateContext1( void** ppImmediateContext );
+
+    HRESULT CreateDeferredContext1(
+            UINT ContextFlags, // Reserved parameter; must be 0
+            [out, retval] IUnknown** ppDeferredContext );
+
+    HRESULT CreateBlendState1(
+        void* pBlendStateDesc,
+        [out, retval] IUnknown** ppBlendState );
+
+    HRESULT CreateRasterizerState1(
+        void* pRasterizerDesc,
+        [out, retval] IUnknown** ppRasterizerState );
+
+    HRESULT CreateDeviceContextState(
+        UINT Flags,
+        void* pFeatureLevels,
+        UINT FeatureLevels,
+        UINT SDKVersion,
+        GUID* EmulatedInterface,
+        void* pChosenFeatureLevel,
+        [out, retval] IUnknown** ppContextState);
+
+    HRESULT OpenSharedResource1(
+        IntPtr hResource,
+        Guid* ReturnedInterface,
+        [out, retval] IUnknown** ppResource);
+
+    HRESULT OpenSharedResourceByName(
+        LPCWSTR lpName,
+        DWORD dwDesiredAccess,
+        REFIID returnedInterface,
+        void** ppResource);
+};
+
 
 [uuid( 6f15aaf2-d208-4e89-9ab4-489535d34f9c)]
 interface ID3D11Texture2D : IUnknown

+ 11 - 3
src/Windows/Avalonia.Win32/OpenGl/Angle/AngleExternalObjectsFeature.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using Avalonia.OpenGL;
 using Avalonia.OpenGL.Egl;
 using Avalonia.Platform;
@@ -13,12 +14,14 @@ internal class AngleExternalObjectsFeature : IGlContextExternalObjectsFeature, I
 {
     private readonly EglContext _context;
     private readonly ID3D11Device _device;
+    private readonly ID3D11Device1 _device1;
 
     public AngleExternalObjectsFeature(EglContext context)
     {
         _context = context;
         var angle = (AngleWin32EglDisplay)context.Display;
         _device = MicroComRuntime.CreateProxyFor<ID3D11Device>(angle.GetDirect3DDevice(), false).CloneReference();
+        _device1 = _device.QueryInterface<ID3D11Device1>();
         using var dxgiDevice = _device.QueryInterface<IDXGIDevice>();
         using var adapter = dxgiDevice.Adapter;
         DeviceLuid = BitConverter.GetBytes(adapter.Desc.AdapterLuid);
@@ -26,7 +29,8 @@ internal class AngleExternalObjectsFeature : IGlContextExternalObjectsFeature, I
 
     public IReadOnlyList<string> SupportedImportableExternalImageTypes { get; } = new[]
     {
-        KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle
+        KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle,
+        KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureNtHandle,
     };
 
     public IReadOnlyList<string> SupportedExportableExternalImageTypes => SupportedImportableExternalImageTypes;
@@ -70,13 +74,17 @@ internal class AngleExternalObjectsFeature : IGlContextExternalObjectsFeature, I
 
     public unsafe IGlExternalImageTexture ImportImage(IPlatformHandle handle, PlatformGraphicsExternalImageProperties properties)
     {
-        if (handle.HandleDescriptor != KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle)
+        if (!SupportedImportableExternalImageTypes.Contains(handle.HandleDescriptor))
             throw new NotSupportedException("Unsupported external memory type");
         
         using (_context.EnsureCurrent())
         {
             var guid = MicroComRuntime.GetGuidFor(typeof(ID3D11Texture2D));
-            using var opened = _device.OpenSharedResource(handle.Handle, &guid);
+            using var opened =
+                handle.HandleDescriptor ==
+                KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle ?
+                    _device.OpenSharedResource(handle.Handle, &guid) :
+                    _device1.OpenSharedResource1(handle.Handle, &guid);
             using var texture = opened.QueryInterface<ID3D11Texture2D>();
             return new AngleExternalMemoryD3D11Texture2D(_context, texture, properties);
         }