diff --git a/samples/GpuInterop/VulkanDemo/D3DMemoryHelper.cs b/samples/GpuInterop/VulkanDemo/D3DMemoryHelper.cs index a0b7d32d3b..ac09c48ccd 100644 --- a/samples/GpuInterop/VulkanDemo/D3DMemoryHelper.cs +++ b/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 }); } diff --git a/samples/GpuInterop/VulkanDemo/VulkanContext.cs b/samples/GpuInterop/VulkanDemo/VulkanContext.cs index 3fdd9695f2..1d44549089 100644 --- a/samples/GpuInterop/VulkanDemo/VulkanContext.cs +++ b/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; diff --git a/samples/GpuInterop/VulkanDemo/VulkanImage.cs b/samples/GpuInterop/VulkanDemo/VulkanImage.cs index 59b2ef7e30..dfb6ba20e0 100644 --- a/samples/GpuInterop/VulkanDemo/VulkanImage.cs +++ b/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; } @@ -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(); - _win32ShareHandle = dxgi.SharedHandle; + using var dxgi = _d3dTexture2D.QueryInterface(); + 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(); + 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; diff --git a/src/Windows/Avalonia.Win32/DirectX/directx.idl b/src/Windows/Avalonia.Win32/DirectX/directx.idl index 1d66c898db..120d1d5159 100644 --- a/src/Windows/Avalonia.Win32/DirectX/directx.idl +++ b/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 diff --git a/src/Windows/Avalonia.Win32/OpenGl/Angle/AngleExternalObjectsFeature.cs b/src/Windows/Avalonia.Win32/OpenGl/Angle/AngleExternalObjectsFeature.cs index a7b52e953e..4349da85c8 100644 --- a/src/Windows/Avalonia.Win32/OpenGl/Angle/AngleExternalObjectsFeature.cs +++ b/src/Windows/Avalonia.Win32/OpenGl/Angle/AngleExternalObjectsFeature.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Runtime.CompilerServices; using Avalonia.Controls.Documents; using Avalonia.OpenGL; @@ -15,12 +16,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(angle.GetDirect3DDevice(), false).CloneReference(); + _device1 = _device.QueryInterface(); using var dxgiDevice = _device.QueryInterface(); using var adapter = dxgiDevice.Adapter; DeviceLuid = BitConverter.GetBytes(adapter.Desc.AdapterLuid); @@ -28,7 +31,8 @@ internal class AngleExternalObjectsFeature : IGlContextExternalObjectsFeature, I public IReadOnlyList SupportedImportableExternalImageTypes { get; } = new[] { - KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle + KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle, + KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureNtHandle, }; public IReadOnlyList SupportedExportableExternalImageTypes => SupportedImportableExternalImageTypes; @@ -72,13 +76,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(); return new AngleExternalMemoryD3D11Texture2D(_context, texture, properties); }