Bläddra i källkod

Use Silk.NET in GpuInterop sample (#20133)

* Replace SharpDX with Silk.NET in GpuInterop sample

* Add Vulkan/D3D11 command line switch to GpuInterop

* Fixed warnings in GpuInterop
Julien Lebosquain 1 vecka sedan
förälder
incheckning
4357a8dafc

+ 3 - 1
samples/GpuInterop/App.axaml.cs

@@ -6,6 +6,8 @@ namespace GpuInterop
 {
 {
     public class App : Application
     public class App : Application
     {
     {
+        public DemoType DemoType { get; set; }
+
         public override void Initialize()
         public override void Initialize()
         {
         {
             AvaloniaXamlLoader.Load(this);
             AvaloniaXamlLoader.Load(this);
@@ -15,7 +17,7 @@ namespace GpuInterop
         {
         {
             if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime)
             if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime)
             {
             {
-                desktopLifetime.MainWindow = new MainWindow();
+                desktopLifetime.MainWindow = new MainWindow(DemoType);
             }
             }
         }
         }
     }
     }

+ 105 - 82
samples/GpuInterop/D3DDemo/D3D11DemoControl.cs

@@ -5,57 +5,79 @@ using System.Numerics;
 using Avalonia;
 using Avalonia;
 using Avalonia.Platform;
 using Avalonia.Platform;
 using Avalonia.Rendering.Composition;
 using Avalonia.Rendering.Composition;
-using SharpDX;
-using SharpDX.Direct3D11;
-using SharpDX.DXGI;
-using SharpDX.Mathematics.Interop;
-using Buffer = SharpDX.Direct3D11.Buffer;
-using DxgiFactory1 = SharpDX.DXGI.Factory1;
-using Matrix = SharpDX.Matrix;
-using D3DDevice = SharpDX.Direct3D11.Device;
-using FeatureLevel = SharpDX.Direct3D.FeatureLevel;
-using Vector3 = SharpDX.Vector3;
+using Silk.NET.Core.Native;
+using Silk.NET.Direct3D11;
+using Silk.NET.DXGI;
+using static Silk.NET.Core.Native.SilkMarshal;
 
 
 namespace GpuInterop.D3DDemo;
 namespace GpuInterop.D3DDemo;
 
 
 public class D3D11DemoControl : DrawingSurfaceDemoBase
 public class D3D11DemoControl : DrawingSurfaceDemoBase
 {
 {
-    private D3DDevice? _device;
+    private ComPtr<ID3D11Device> _device;
     private D3D11Swapchain? _swapchain;
     private D3D11Swapchain? _swapchain;
-    private DeviceContext? _context;
-    private Matrix _view;
+    private ComPtr<ID3D11DeviceContext> _context;
+    private Matrix4x4 _view;
     private PixelSize _lastSize;
     private PixelSize _lastSize;
-    private Texture2D? _depthBuffer;
-    private DepthStencilView? _depthView;
-    private Matrix _proj;
-    private Buffer? _constantBuffer;
+    private ComPtr<ID3D11Texture2D> _depthBuffer;
+    private ComPtr<ID3D11DepthStencilView> _depthView;
+    private Matrix4x4 _proj;
+    private ComPtr<ID3D11Buffer> _constantBuffer;
     private readonly Stopwatch _st = Stopwatch.StartNew();
     private readonly Stopwatch _st = Stopwatch.StartNew();
 
 
-    protected override (bool success, string info) InitializeGraphicsResources(Compositor compositor,
+    protected override unsafe (bool success, string info) InitializeGraphicsResources(Compositor compositor,
         CompositionDrawingSurface surface, ICompositionGpuInterop interop)
         CompositionDrawingSurface surface, ICompositionGpuInterop interop)
     {
     {
         if (interop.SupportedImageHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes
         if (interop.SupportedImageHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes
                 .D3D11TextureGlobalSharedHandle) != true)
                 .D3D11TextureGlobalSharedHandle) != true)
             return (false, "DXGI shared handle import is not supported by the current graphics backend");
             return (false, "DXGI shared handle import is not supported by the current graphics backend");
-        
-        var factory = new DxgiFactory1();
-        using var adapter = factory.GetAdapter1(0);
-        _device = new D3DDevice(adapter, DeviceCreationFlags.None, new[]
+
+        using var dxgi = new DXGI(DXGI.CreateDefaultContext(["DXGI.dll"]));
+        using var d3d11 = new D3D11(D3D11.CreateDefaultContext(["d3d11.dll"]));
+        using var factory = dxgi.CreateDXGIFactory1<IDXGIFactory1>();
+
+        using ComPtr<IDXGIAdapter> adapter = default;
+        ThrowHResult(factory.EnumAdapters(0, adapter.GetAddressOf()));
+
+        const int featureLevelCount = 8;
+        var featureLevels = stackalloc D3DFeatureLevel[featureLevelCount]
         {
         {
-            FeatureLevel.Level_12_1,
-            FeatureLevel.Level_12_0,
-            FeatureLevel.Level_11_1,
-            FeatureLevel.Level_11_0,
-            FeatureLevel.Level_10_0,
-            FeatureLevel.Level_9_3,
-            FeatureLevel.Level_9_2,
-            FeatureLevel.Level_9_1,
-        });
-        _swapchain = new D3D11Swapchain(_device, interop, surface);
-        _context = _device.ImmediateContext;
+            D3DFeatureLevel.Level121,
+            D3DFeatureLevel.Level120,
+            D3DFeatureLevel.Level111,
+            D3DFeatureLevel.Level110,
+            D3DFeatureLevel.Level100,
+            D3DFeatureLevel.Level93,
+            D3DFeatureLevel.Level92,
+            D3DFeatureLevel.Level91
+        };
+
+        ComPtr<ID3D11Device> device = default;
+        ComPtr<ID3D11DeviceContext> context = default;
+        D3DFeatureLevel actualFeatureLevel;
+        ThrowHResult(d3d11.CreateDevice(
+            adapter,
+            D3DDriverType.Unknown,
+            IntPtr.Zero,
+            0u,
+            featureLevels,
+            featureLevelCount,
+            D3D11.SdkVersion,
+            device.GetAddressOf(),
+            &actualFeatureLevel,
+            context.GetAddressOf()));
+
+        _device = device;
+        _swapchain = new D3D11Swapchain(device, interop, surface);
+        _context = context;
         _constantBuffer = D3DContent.CreateMesh(_device);
         _constantBuffer = D3DContent.CreateMesh(_device);
-        _view = Matrix.LookAtLH(new Vector3(0, 0, -5), new Vector3(0, 0, 0), Vector3.UnitY);
-        return (true, $"D3D11 ({_device.FeatureLevel}) {adapter.Description1.Description}");
+        _view = Matrix4x4.CreateLookAtLeftHanded(new Vector3(0, 0, -5), new Vector3(0, 0, 0), Vector3.UnitY);
+
+        AdapterDesc adapterDesc;
+        ThrowHResult(adapter.GetDesc(&adapterDesc));
+        var description = PtrToString((IntPtr)adapterDesc.Description, NativeStringEncoding.LPWStr);
+
+        return (true, $"D3D11 ({actualFeatureLevel}) {description}");
     }
     }
 
 
     protected override void FreeGraphicsResources()
     protected override void FreeGraphicsResources()
@@ -66,16 +88,16 @@ public class D3D11DemoControl : DrawingSurfaceDemoBase
             _swapchain = null;
             _swapchain = null;
         }
         }
 
 
-        Utilities.Dispose(ref _depthView);
-        Utilities.Dispose(ref _depthBuffer);
-        Utilities.Dispose(ref _constantBuffer);
-        Utilities.Dispose(ref _context);
-        Utilities.Dispose(ref _device);
+        _depthView.Dispose();
+        _depthBuffer.Dispose();
+        _constantBuffer.Dispose();
+        _context.Dispose();
+        _device.Dispose();
     }
     }
 
 
     protected override bool SupportsDisco => true;
     protected override bool SupportsDisco => true;
 
 
-    protected override void RenderFrame(PixelSize pixelSize)
+    protected override unsafe void RenderFrame(PixelSize pixelSize)
     {
     {
         if (pixelSize == default)
         if (pixelSize == default)
             return;
             return;
@@ -86,69 +108,70 @@ public class D3D11DemoControl : DrawingSurfaceDemoBase
         }
         }
         using (_swapchain!.BeginDraw(pixelSize, out var renderView))
         using (_swapchain!.BeginDraw(pixelSize, out var renderView))
         {
         {
-            
-            _device!.ImmediateContext.OutputMerger.SetTargets(_depthView, renderView);
-            var viewProj = Matrix.Multiply(_view, _proj);
-            var context = _device.ImmediateContext;
+            var renderViewHandle = renderView.Handle;
+            _context.OMSetRenderTargets(1, &renderViewHandle, _depthView);
+            var viewProj = _view * _proj;
 
 
             var now = _st.Elapsed.TotalSeconds * 5;
             var now = _st.Elapsed.TotalSeconds * 5;
             var scaleX = (float)(1f + Disco * (Math.Sin(now) + 1) / 6);
             var scaleX = (float)(1f + Disco * (Math.Sin(now) + 1) / 6);
             var scaleY = (float)(1f + Disco * (Math.Cos(now) + 1) / 8);
             var scaleY = (float)(1f + Disco * (Math.Cos(now) + 1) / 8);
             var colorOff =(float) (Math.Sin(now) + 1) / 2 * Disco;
             var colorOff =(float) (Math.Sin(now) + 1) / 2 * Disco;
             
             
-            
             // Clear views
             // Clear views
-            context.ClearDepthStencilView(_depthView, DepthStencilClearFlags.Depth, 1.0f, 0);
-            context.ClearRenderTargetView(renderView,
-                new RawColor4(1 - colorOff, colorOff, (float)0.5 + colorOff / 2, 1));
+            _context.ClearDepthStencilView(_depthView, (uint)ClearFlag.Depth, 1.0f, 0);
+            var color = new Vector4(1f - colorOff, colorOff, 0.5f + colorOff * 0.5f, 1.0f);
+            _context.ClearRenderTargetView(renderView, (float*)&color);
 
 
-            
-            var ypr = Matrix4x4.CreateFromYawPitchRoll(Yaw, Pitch, Roll);
             // Update WorldViewProj Matrix
             // Update WorldViewProj Matrix
-            var worldViewProj = Matrix.RotationX(Yaw) * Matrix.RotationY(Pitch)
-                                                      * Matrix.RotationZ(Roll)
-                                                      * Matrix.Scaling(new Vector3(scaleX, scaleY, 1))
-                                                      * viewProj;
-            worldViewProj.Transpose();
-            context.UpdateSubresource(ref worldViewProj, _constantBuffer);
+            var ypr = Matrix4x4.CreateFromYawPitchRoll(Yaw, Pitch, Roll);
+            var worldViewProj = ypr * Matrix4x4.CreateScale(new Vector3(scaleX, scaleY, 1)) * viewProj;
+            worldViewProj = Matrix4x4.Transpose(worldViewProj);
+
+            _context.UpdateSubresource(_constantBuffer, 0, null, &worldViewProj, 0, 0);
 
 
             // Draw the cube
             // Draw the cube
-            context.Draw(36, 0);
+            _context.Draw(36, 0);
             
             
-            
-            _context!.Flush();
+            _context.Flush();
         }
         }
     }
     }
 
 
-    private void Resize(PixelSize size)
+    private unsafe void Resize(PixelSize size)
     {
     {
-        Utilities.Dispose(ref _depthBuffer);
+        _depthBuffer.Dispose();
 
 
-        if (_device is null)
+        if (_device.Handle == null)
             return;
             return;
 
 
-        _depthBuffer = new Texture2D(_device,
-            new Texture2DDescription()
-            {
-                Format = Format.D32_Float_S8X24_UInt,
-                ArraySize = 1,
-                MipLevels = 1,
-                Width = size.Width,
-                Height = size.Height,
-                SampleDescription = new SampleDescription(1, 0),
-                Usage = ResourceUsage.Default,
-                BindFlags = BindFlags.DepthStencil,
-                CpuAccessFlags = CpuAccessFlags.None,
-                OptionFlags = ResourceOptionFlags.None
-            });
-
-        Utilities.Dispose(ref _depthView);
-        _depthView = new DepthStencilView(_device, _depthBuffer);
+        ComPtr<ID3D11Texture2D> depthBuffer = default;
+        var textureDesc = new Texture2DDesc
+        {
+            Format = Format.FormatD32FloatS8X24Uint,
+            ArraySize = 1,
+            MipLevels = 1,
+            Width = (uint)size.Width,
+            Height = (uint)size.Height,
+            SampleDesc = new SampleDesc(1, 0),
+            Usage = Usage.Default,
+            BindFlags = (uint)BindFlag.DepthStencil,
+            CPUAccessFlags = (uint)CpuAccessFlag.None,
+            MiscFlags = (uint)ResourceMiscFlag.None
+        };
+        ThrowHResult(_device.CreateTexture2D(
+            &textureDesc,
+            (SubresourceData*)null,
+            depthBuffer.GetAddressOf()));
+
+        _depthBuffer = depthBuffer;
+
+        _depthView.Dispose();
+        ThrowHResult(_device.CreateDepthStencilView(_depthBuffer, null, ref _depthView));
 
 
         // Setup targets and viewport for rendering
         // Setup targets and viewport for rendering
-        _device.ImmediateContext.Rasterizer.SetViewport(new Viewport(0, 0, size.Width, size.Height, 0.0f, 1.0f));
+        var viewport = new Viewport(0, 0, size.Width, size.Height, 0.0f, 1.0f);
+        _context.RSSetViewports(1, &viewport);
         
         
         // Setup new projection matrix with correct aspect ratio
         // Setup new projection matrix with correct aspect ratio
-        _proj = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, size.Width / (float) size.Height, 0.1f, 100.0f);
+        _proj = Matrix4x4.CreatePerspectiveFieldOfViewLeftHanded((float)Math.PI / 4.0f, size.Width / (float) size.Height, 0.1f, 100.0f);
     }
     }
 }
 }

+ 47 - 33
samples/GpuInterop/D3DDemo/D3D11Swapchain.cs

@@ -1,22 +1,22 @@
 using System;
 using System;
+using System.Runtime.CompilerServices;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using Avalonia;
 using Avalonia;
 using Avalonia.Platform;
 using Avalonia.Platform;
 using Avalonia.Rendering;
 using Avalonia.Rendering;
 using Avalonia.Rendering.Composition;
 using Avalonia.Rendering.Composition;
-using SharpDX.Direct3D11;
-using SharpDX.DXGI;
-using DxgiFactory1 = SharpDX.DXGI.Factory1;
-using D3DDevice = SharpDX.Direct3D11.Device;
-using DxgiResource = SharpDX.DXGI.Resource;
+using Silk.NET.Core.Native;
+using Silk.NET.Direct3D11;
+using Silk.NET.DXGI;
+using static Silk.NET.Core.Native.SilkMarshal;
 
 
 namespace GpuInterop.D3DDemo;
 namespace GpuInterop.D3DDemo;
 
 
 class D3D11Swapchain : SwapchainBase<D3D11SwapchainImage>
 class D3D11Swapchain : SwapchainBase<D3D11SwapchainImage>
 {
 {
-    private readonly D3DDevice _device;
+    private readonly ComPtr<ID3D11Device> _device;
 
 
-    public D3D11Swapchain(D3DDevice device, ICompositionGpuInterop interop, CompositionDrawingSurface target)
+    public D3D11Swapchain(ComPtr<ID3D11Device> device, ICompositionGpuInterop interop, CompositionDrawingSurface target)
         : base(interop, target)
         : base(interop, target)
     {
     {
         _device = device;
         _device = device;
@@ -24,7 +24,7 @@ class D3D11Swapchain : SwapchainBase<D3D11SwapchainImage>
 
 
     protected override D3D11SwapchainImage CreateImage(PixelSize size) => new(_device, size, Interop, Target);
     protected override D3D11SwapchainImage CreateImage(PixelSize size) => new(_device, size, Interop, Target);
 
 
-    public IDisposable BeginDraw(PixelSize size, out RenderTargetView view)
+    public IDisposable BeginDraw(PixelSize size, out ComPtr<ID3D11RenderTargetView> view)
     {
     {
         var rv = BeginDrawCore(size, out var image);
         var rv = BeginDrawCore(size, out var image);
         view = image.RenderTargetView;
         view = image.RenderTargetView;
@@ -37,53 +37,67 @@ public class D3D11SwapchainImage : ISwapchainImage
     public PixelSize Size { get; }
     public PixelSize Size { get; }
     private readonly ICompositionGpuInterop _interop;
     private readonly ICompositionGpuInterop _interop;
     private readonly CompositionDrawingSurface _target;
     private readonly CompositionDrawingSurface _target;
-    private readonly Texture2D _texture;
-    private readonly KeyedMutex _mutex;
+    private ComPtr<ID3D11Texture2D> _texture;
+    private ComPtr<IDXGIKeyedMutex> _mutex;
+    private ComPtr<ID3D11RenderTargetView> _renderTargetView;
     private readonly IntPtr _handle;
     private readonly IntPtr _handle;
     private PlatformGraphicsExternalImageProperties _properties;
     private PlatformGraphicsExternalImageProperties _properties;
     private ICompositionImportedGpuImage? _imported;
     private ICompositionImportedGpuImage? _imported;
+
     public Task? LastPresent { get; private set; }
     public Task? LastPresent { get; private set; }
-    public RenderTargetView RenderTargetView { get; }
+    public ComPtr<ID3D11RenderTargetView> RenderTargetView => _renderTargetView;
 
 
-    public D3D11SwapchainImage(D3DDevice device, PixelSize size,
+    public unsafe D3D11SwapchainImage(
+        ComPtr<ID3D11Device> device,
+        PixelSize size,
         ICompositionGpuInterop interop,
         ICompositionGpuInterop interop,
         CompositionDrawingSurface target)
         CompositionDrawingSurface target)
     {
     {
         Size = size;
         Size = size;
         _interop = interop;
         _interop = interop;
         _target = target;
         _target = target;
-        _texture = new Texture2D(device,
-            new Texture2DDescription
-            {
-                Format = Format.R8G8B8A8_UNorm,
-                Width = size.Width,
-                Height = size.Height,
-                ArraySize = 1,
-                MipLevels = 1,
-                SampleDescription = new SampleDescription { Count = 1, Quality = 0 },
-                CpuAccessFlags = default,
-                OptionFlags = ResourceOptionFlags.SharedKeyedmutex,
-                BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource
-            });
-        _mutex = _texture.QueryInterface<KeyedMutex>();
-        using (var res = _texture.QueryInterface<DxgiResource>())
-            _handle = res.SharedHandle;
+
+        ComPtr<ID3D11Texture2D> texture = default;
+        var textureDesc = new Texture2DDesc
+        {
+            Format = Format.FormatR8G8B8A8Unorm,
+            Width = (uint)size.Width,
+            Height = (uint)size.Height,
+            ArraySize = 1,
+            MipLevels = 1,
+            SampleDesc = new SampleDesc(1, 0),
+            Usage = Usage.Default,
+            BindFlags = (uint)(BindFlag.RenderTarget | BindFlag.ShaderResource),
+            CPUAccessFlags = 0,
+            MiscFlags = (uint)ResourceMiscFlag.SharedKeyedmutex
+        };
+        ThrowHResult(device.CreateTexture2D(&textureDesc, (SubresourceData*)null, texture.GetAddressOf()));
+        _texture = texture;
+
+        _mutex = _texture.QueryInterface<IDXGIKeyedMutex>();
+        using (var res = _texture.QueryInterface<IDXGIResource>())
+        {
+            void* handle = null;
+            ThrowHResult(res.GetSharedHandle(ref handle));
+            _handle = (IntPtr)handle;
+        }
+
         _properties = new PlatformGraphicsExternalImageProperties
         _properties = new PlatformGraphicsExternalImageProperties
         {
         {
             Width = size.Width, Height = size.Height, Format = PlatformGraphicsExternalImageFormat.B8G8R8A8UNorm
             Width = size.Width, Height = size.Height, Format = PlatformGraphicsExternalImageFormat.B8G8R8A8UNorm
         };
         };
 
 
-        RenderTargetView = new RenderTargetView(device, _texture);
+        ThrowHResult(device.CreateRenderTargetView(_texture, null, ref _renderTargetView));
     }
     }
 
 
     public void BeginDraw()
     public void BeginDraw()
     {
     {
-        _mutex.Acquire(0, int.MaxValue);
+        _mutex.AcquireSync(0, int.MaxValue);
     }
     }
 
 
     public void Present()
     public void Present()
     {
     {
-        _mutex.Release(1);
+        _mutex.ReleaseSync(1);
         _imported ??= _interop.ImportImage(
         _imported ??= _interop.ImportImage(
             new PlatformHandle(_handle, KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle),
             new PlatformHandle(_handle, KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle),
             _properties);
             _properties);
@@ -103,8 +117,8 @@ public class D3D11SwapchainImage : ISwapchainImage
                 // Ignore
                 // Ignore
             }
             }
 
 
-        RenderTargetView.Dispose();
+        _renderTargetView.Dispose();
         _mutex.Dispose();
         _mutex.Dispose();
         _texture.Dispose();
         _texture.Dispose();
     }
     }
-}
+}

+ 136 - 88
samples/GpuInterop/D3DDemo/D3DContent.cs

@@ -1,110 +1,158 @@
-using SharpDX;
-using SharpDX.D3DCompiler;
-using SharpDX.Direct3D;
-
-using System;
-using System.Linq;
-using System.Threading.Tasks;
-using SharpDX.Direct2D1;
-using SharpDX.Direct3D11;
-using SharpDX.DXGI;
-using SharpDX.Mathematics.Interop;
-using Buffer = SharpDX.Direct3D11.Buffer;
-using DeviceContext = SharpDX.Direct2D1.DeviceContext;
-using DxgiFactory1 = SharpDX.DXGI.Factory1;
-using Matrix = SharpDX.Matrix;
-using D3DDevice = SharpDX.Direct3D11.Device;
-using DxgiResource = SharpDX.DXGI.Resource;
-using FeatureLevel = SharpDX.Direct3D.FeatureLevel;
-using InputElement = SharpDX.Direct3D11.InputElement;
-
+using System.Numerics;
+using Silk.NET.Core.Native;
+using Silk.NET.Direct3D.Compilers;
+using Silk.NET.Direct3D11;
+using Silk.NET.DXGI;
+using static Silk.NET.Core.Native.SilkMarshal;
 
 
 namespace GpuInterop.D3DDemo;
 namespace GpuInterop.D3DDemo;
 
 
-public class D3DContent
+public static class D3DContent
 {
 {
+    private static D3DCompiler s_compiler = D3DCompiler.GetApi();
 
 
-    public static Buffer CreateMesh(D3DDevice device)
+    public static unsafe ComPtr<ID3D11Buffer> CreateMesh(ComPtr<ID3D11Device> device)
     {
     {
         // Compile Vertex and Pixel shaders
         // Compile Vertex and Pixel shaders
-        var vertexShaderByteCode = ShaderBytecode.CompileFromFile("D3DDemo\\MiniCube.fx", "VS", "vs_4_0");
-        var vertexShader = new VertexShader(device, vertexShaderByteCode);
+        using var vertexShaderByteCode = CompileShader("D3DDemo\\MiniCube.fx", "VS", "vs_4_0");
+        using ComPtr<ID3D11VertexShader> vertexShader = default;
+        ThrowHResult(device.CreateVertexShader(
+            vertexShaderByteCode.GetBufferPointer(),
+            vertexShaderByteCode.GetBufferSize(),
+            (ID3D11ClassLinkage*)null,
+            vertexShader.GetAddressOf()));
 
 
-        var pixelShaderByteCode = ShaderBytecode.CompileFromFile("D3DDemo\\MiniCube.fx", "PS", "ps_4_0");
-        var pixelShader = new PixelShader(device, pixelShaderByteCode);
+        using var pixelShaderByteCode = CompileShader("D3DDemo\\MiniCube.fx", "PS", "ps_4_0");
+        using ComPtr<ID3D11PixelShader> pixelShader = default;
+        ThrowHResult(device.CreatePixelShader(
+            pixelShaderByteCode.GetBufferPointer(),
+            pixelShaderByteCode.GetBufferSize(),
+            (ID3D11ClassLinkage*)null,
+            pixelShader.GetAddressOf()));
 
 
-        var signature = ShaderSignature.GetInputSignature(vertexShaderByteCode);
+        using ComPtr<ID3D10Blob> vertexShaderSignature = default;
+        ThrowHResult(s_compiler.GetInputSignatureBlob(
+            vertexShaderByteCode.GetBufferPointer(),
+            vertexShaderByteCode.GetBufferSize(),
+            vertexShaderSignature.GetAddressOf()));
 
 
-        var inputElements = new[]
+        // Layout from VertexShader input signature
+        using ComPtr<ID3D11InputLayout> inputLayout = default;
+        var positionNamePtr = StringToPtr("POSITION", NativeStringEncoding.LPStr);
+        var colorNamePtr = StringToPtr("COLOR", NativeStringEncoding.LPStr);
+        try
         {
         {
-            new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
-            new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0)
-        };
+            const int inputCount = 2;
+            var inputs = stackalloc InputElementDesc[inputCount]
+            {
+                new InputElementDesc((byte*)positionNamePtr, 0, Format.FormatR32G32B32A32Float, 0, 0),
+                new InputElementDesc((byte*)colorNamePtr, 0, Format.FormatR32G32B32A32Float, 0, 16)
+            };
 
 
-        // Layout from VertexShader input signature
-        var layout = new InputLayout(
-            device,
-            signature,
-            inputElements);
+            ThrowHResult(device.CreateInputLayout(
+                inputs,
+                inputCount,
+                vertexShaderSignature.GetBufferPointer(),
+                vertexShaderSignature.GetBufferSize(),
+                inputLayout.GetAddressOf()));
+        }
+        finally
+        {
+            FreeString(positionNamePtr, NativeStringEncoding.LPStr);
+            FreeString(colorNamePtr, NativeStringEncoding.LPStr);
+        }
 
 
         // Instantiate Vertex buffer from vertex data
         // Instantiate Vertex buffer from vertex data
-        using var vertices = Buffer.Create(
-            device,
-            BindFlags.VertexBuffer,
-            new[]
+        var vertices = new[]
+        {
+            new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Front
+            new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
+            new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
+            new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
+            new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
+            new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
+            new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), // BACK
+            new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
+            new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
+            new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
+            new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
+            new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
+            new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), // Top
+            new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
+            new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
+            new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
+            new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
+            new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
+            new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), // Bottom
+            new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
+            new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
+            new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
+            new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
+            new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
+            new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), // Left
+            new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
+            new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
+            new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
+            new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
+            new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
+            new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), // Right
+            new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
+            new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
+            new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
+            new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
+            new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
+        };
+
+        using ComPtr<ID3D11Buffer> vertexBuffer = default;
+
+        fixed (Vector4* verticesPtr = vertices)
+        {
+            var vertexBufferDesc = new BufferDesc
             {
             {
-                new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Front
-                new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
-                new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
-                new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
-                new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
-                new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
-                new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), // BACK
-                new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
-                new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
-                new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
-                new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
-                new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
-                new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), // Top
-                new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
-                new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
-                new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
-                new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
-                new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
-                new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), // Bottom
-                new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
-                new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
-                new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
-                new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
-                new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
-                new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), // Left
-                new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
-                new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
-                new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
-                new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
-                new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
-                new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), // Right
-                new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
-                new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
-                new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
-                new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
-                new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
-            });
+                ByteWidth = (uint)(sizeof(Vector4) * vertices.Length),
+                Usage = Usage.Default,
+                BindFlags = (uint)BindFlag.VertexBuffer,
+                CPUAccessFlags = (uint)CpuAccessFlag.None,
+                MiscFlags = (uint)ResourceMiscFlag.None,
+                StructureByteStride = 0
+            };
+            var subresourceData = new SubresourceData(verticesPtr);
+            ThrowHResult(device.CreateBuffer(&vertexBufferDesc, &subresourceData, vertexBuffer.GetAddressOf()));
+        }
 
 
         // Create Constant Buffer
         // Create Constant Buffer
-        var constantBuffer = new Buffer(device, Utilities.SizeOf<Matrix>(), ResourceUsage.Default,
-            BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
-
-        var context = device.ImmediateContext;
+        ComPtr<ID3D11Buffer> constantBuffer = default;
+        var constantBufferDesc = new BufferDesc
+        {
+            ByteWidth = (uint)sizeof(Matrix4x4),
+            Usage = Usage.Default,
+            BindFlags = (uint)BindFlag.ConstantBuffer,
+            CPUAccessFlags = (uint)CpuAccessFlag.None,
+            MiscFlags = (uint)ResourceMiscFlag.None,
+            StructureByteStride = 0
+        };
+        ThrowHResult(device.CreateBuffer(&constantBufferDesc, (SubresourceData*)null, constantBuffer.GetAddressOf()));
 
 
         // Prepare All the stages
         // Prepare All the stages
-        context.InputAssembler.InputLayout = layout;
-        context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
-        context.InputAssembler.SetVertexBuffers(0,
-            new VertexBufferBinding(vertices, Utilities.SizeOf<Vector4>() * 2, 0));
-        context.VertexShader.SetConstantBuffer(0, constantBuffer);
-        context.VertexShader.Set(vertexShader);
-        context.PixelShader.Set(pixelShader);
+        using ComPtr<ID3D11DeviceContext> context = default;
+        device.GetImmediateContext(context.GetAddressOf());
+
+        context.IASetInputLayout(inputLayout);
+        context.IASetPrimitiveTopology(D3DPrimitiveTopology.D3D10PrimitiveTopologyTrianglelist);
+        var stride = (uint)(sizeof(Vector4) * 2);
+        var offset = 0u;
+        context.IASetVertexBuffers(0, 1, &vertexBuffer.Handle, &stride, &offset);
+        context.VSSetConstantBuffers(0, 1, &constantBuffer.Handle);
+        context.VSSetShader(vertexShader, (ID3D11ClassInstance**)null, 0);
+        context.PSSetShader(pixelShader, (ID3D11ClassInstance**)null, 0);
+
         return constantBuffer;
         return constantBuffer;
     }
     }
+
+    private static unsafe ComPtr<ID3D10Blob> CompileShader(string fileName, string entryPoint, string profile)
+    {
+        ComPtr<ID3D10Blob> blob = default;
+        ThrowHResult(s_compiler.CompileFromFile(fileName, null, null, entryPoint, profile, 0u, 0u, blob.GetAddressOf(), null));
+        return blob;
+    }
 }
 }

+ 7 - 0
samples/GpuInterop/DemoType.cs

@@ -0,0 +1,7 @@
+namespace GpuInterop;
+
+public enum DemoType
+{
+    Vulkan,
+    D3D11
+}

+ 8 - 6
samples/GpuInterop/GpuInterop.csproj

@@ -7,7 +7,6 @@
     <Nullable>enable</Nullable>
     <Nullable>enable</Nullable>
     <GenerateDocumentationFile>false</GenerateDocumentationFile>
     <GenerateDocumentationFile>false</GenerateDocumentationFile>
     <UseD3DCompiler>true</UseD3DCompiler>
     <UseD3DCompiler>true</UseD3DCompiler>
-    <UseSharpDXMathematics>true</UseSharpDXMathematics>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   </PropertyGroup>
 
 
@@ -25,10 +24,13 @@
   </ItemGroup>
   </ItemGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Include="Silk.NET.Vulkan" Version="2.16.0" />
-    <PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.16.0" />
-    <PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.16.0" />
-    <PackageReference Include="System.Reactive" Version="5.0.0" />
+    <PackageReference Include="Silk.NET.Direct3D11" Version="2.22.0" />
+    <PackageReference Include="Silk.NET.Direct3D.Compilers" Version="2.22.0" />
+    <PackageReference Include="Silk.NET.Vulkan" Version="2.22.0" />
+    <PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.22.0" />
+    <PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.22.0" />
+    <!-- Silk.NET 2.22 targets an obsolete System.Text.Json, update to avoid warnings. -->
+    <PackageReference Include="System.Text.Json" Version="10.0.0" />
   </ItemGroup>
   </ItemGroup>
 
 
   <ItemGroup>
   <ItemGroup>
@@ -37,6 +39,7 @@
 
 
   <ItemGroup>
   <ItemGroup>
     <Compile Include="..\..\src\Avalonia.Base\Rendering\SwapchainBase.cs" />
     <Compile Include="..\..\src\Avalonia.Base\Rendering\SwapchainBase.cs" />
+    <Compile Include="..\..\src\Avalonia.Base\Reactive\Disposable.cs" />
     <None Remove="VulkanDemo\Assets\Shaders\frag.spirv" />
     <None Remove="VulkanDemo\Assets\Shaders\frag.spirv" />
     <EmbeddedResource Include="VulkanDemo\Assets\Shaders\frag.spirv" />
     <EmbeddedResource Include="VulkanDemo\Assets\Shaders\frag.spirv" />
     <None Remove="VulkanDemo\Assets\Shaders\vert.spirv" />
     <None Remove="VulkanDemo\Assets\Shaders\vert.spirv" />
@@ -47,5 +50,4 @@
   <Import Project="..\..\build\SampleApp.props" />
   <Import Project="..\..\build\SampleApp.props" />
   <Import Project="..\..\build\ReferenceCoreLibraries.props" />
   <Import Project="..\..\build\ReferenceCoreLibraries.props" />
   <Import Project="..\..\build\BuildTargets.targets" />
   <Import Project="..\..\build\BuildTargets.targets" />
-  <Import Project="..\..\build\SharpDX.props" />
 </Project>
 </Project>

+ 1 - 9
samples/GpuInterop/MainWindow.axaml

@@ -1,13 +1,5 @@
 <Window xmlns="https://github.com/avaloniaui"
 <Window xmlns="https://github.com/avaloniaui"
         xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
         xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
-        xmlns:gpuInterop="clr-namespace:GpuInterop"
-        xmlns:d3DDemo="clr-namespace:GpuInterop.D3DDemo"
-        xmlns:vulkanDemo="clr-namespace:GpuInterop.VulkanDemo"
         x:Class="GpuInterop.MainWindow">
         x:Class="GpuInterop.MainWindow">
-  <gpuInterop:GpuDemo>
-    <gpuInterop:GpuDemo.Demo>
-      <!--<d3DDemo:D3D11DemoControl/>-->
-      <vulkanDemo:VulkanDemoControl/>
-    </gpuInterop:GpuDemo.Demo>
-  </gpuInterop:GpuDemo>
+
 </Window>
 </Window>

+ 21 - 1
samples/GpuInterop/MainWindow.axaml.cs

@@ -1,15 +1,35 @@
+using System;
 using Avalonia;
 using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Controls;
 using Avalonia.Markup.Xaml;
 using Avalonia.Markup.Xaml;
 using Avalonia.Rendering;
 using Avalonia.Rendering;
+using GpuInterop.D3DDemo;
+using GpuInterop.VulkanDemo;
 
 
 namespace GpuInterop
 namespace GpuInterop
 {
 {
     public class MainWindow : Window
     public class MainWindow : Window
     {
     {
-        public MainWindow()
+        public MainWindow() : this(DemoType.Vulkan)
+        {
+        }
+
+        public MainWindow(DemoType demoType)
         {
         {
             InitializeComponent();
             InitializeComponent();
+
+            Title = demoType.ToString();
+
+            Content = new GpuDemo
+            {
+                Demo = demoType switch
+                {
+                    DemoType.Vulkan => new VulkanDemoControl(),
+                    DemoType.D3D11 => new D3D11DemoControl(),
+                    var unknown => throw new InvalidOperationException($"Unknown demo type {unknown}")
+                }
+            };
+
             this.AttachDevTools();
             this.AttachDevTools();
             RendererDiagnostics.DebugOverlays = RendererDebugOverlays.Fps;
             RendererDiagnostics.DebugOverlays = RendererDebugOverlays.Fps;
         }
         }

+ 19 - 13
samples/GpuInterop/Program.cs

@@ -1,29 +1,35 @@
-global using System.Reactive.Disposables;
+using System;
 using Avalonia;
 using Avalonia;
 using Avalonia.Logging;
 using Avalonia.Logging;
 using Avalonia.Vulkan;
 using Avalonia.Vulkan;
 
 
 namespace GpuInterop
 namespace GpuInterop
 {
 {
-    public class Program
+    public static class Program
     {
     {
-        static void Main(string[] args) => BuildAvaloniaApp()
-            .StartWithClassicDesktopLifetime(args);
+        public static void Main(string[] args)
+        {
+            var demoType = OperatingSystem.IsWindows() && args.AsSpan().Contains("--d3d") ? DemoType.D3D11 : DemoType.Vulkan;
+            BuildAvaloniaAppCore(demoType).StartWithClassicDesktopLifetime(args);
+        }
 
 
-        public static AppBuilder BuildAvaloniaApp() =>
-            AppBuilder.Configure<App>()
+        public static AppBuilder BuildAvaloniaApp() => BuildAvaloniaAppCore(DemoType.Vulkan);
+
+        private static AppBuilder BuildAvaloniaAppCore(DemoType demoType) =>
+            AppBuilder
+                .Configure(() => new App { DemoType = demoType })
                 .UsePlatformDetect()
                 .UsePlatformDetect()
                 .With(new Win32PlatformOptions
                 .With(new Win32PlatformOptions
                 {
                 {
-                    RenderingMode = new []
-                    {
-                        Win32RenderingMode.Vulkan
-                    }
+                    RenderingMode = [demoType == DemoType.D3D11 ? Win32RenderingMode.AngleEgl : Win32RenderingMode.Vulkan]
+                })
+                .With(new X11PlatformOptions
+                {
+                    RenderingMode = [X11RenderingMode.Vulkan]
                 })
                 })
-                .With(new X11PlatformOptions(){RenderingMode =new[] { X11RenderingMode.Vulkan } })
-                .With(new VulkanOptions()
+                .With(new VulkanOptions
                 {
                 {
-                    VulkanInstanceCreationOptions = new VulkanInstanceCreationOptions()
+                    VulkanInstanceCreationOptions = new VulkanInstanceCreationOptions
                     {
                     {
                         UseDebug = true
                         UseDebug = true
                     }
                     }

+ 12 - 0
samples/GpuInterop/Properties/launchSettings.json

@@ -0,0 +1,12 @@
+{
+  "$schema": "http://json.schemastore.org/launchsettings.json",
+  "profiles": {
+    "GpuInterop (Vulkan)": {
+      "commandName": "Project",
+    },
+    "GpuInterop (Direct3D)": {
+      "commandName": "Project",
+      "commandLineArgs": "--d3d"
+    }
+  }
+}

+ 80 - 37
samples/GpuInterop/VulkanDemo/D3DMemoryHelper.cs

@@ -1,54 +1,97 @@
 using System;
 using System;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
 using Avalonia;
 using Avalonia;
-using SharpDX.Direct3D;
-using SharpDX.Direct3D11;
-using SharpDX.DXGI;
-using D3DDevice = SharpDX.Direct3D11.Device;
-using DxgiFactory1 = SharpDX.DXGI.Factory1;
+using Silk.NET.Core.Native;
+using Silk.NET.Direct3D11;
+using Silk.NET.DXGI;
+using VulkanFormat = Silk.NET.Vulkan.Format;
+using static Silk.NET.Core.Native.SilkMarshal;
+
 namespace GpuInterop.VulkanDemo;
 namespace GpuInterop.VulkanDemo;
 
 
 public class D3DMemoryHelper
 public class D3DMemoryHelper
 {
 {
-    public static D3DDevice CreateDeviceByLuid(Span<byte> luid)
+    private const int DxgiErrorNotFound = unchecked((int)0x887A0002);
+
+    public static unsafe ComPtr<ID3D11Device> CreateDeviceByLuid(Luid luid)
     {
     {
-        var factory = new DxgiFactory1();
-        var longLuid = MemoryMarshal.Cast<byte, long>(luid)[0];
-        for (var c = 0; c < factory.GetAdapterCount1(); c++)
+        using var dxgi = new DXGI(DXGI.CreateDefaultContext(["DXGI.dll"]));
+        using var d3d11 = new D3D11(D3D11.CreateDefaultContext(["d3d11.dll"]));
+        using var factory = dxgi.CreateDXGIFactory1<IDXGIFactory1>();
+        using var adapter = GetAdapterByLuid(factory, luid);
+
+        const int featureLevelCount = 8;
+        var featureLevels = stackalloc D3DFeatureLevel[featureLevelCount]
         {
         {
-            using var adapter = factory.GetAdapter1(c);
-            if (adapter.Description1.Luid != longLuid)
-                continue;
-
-            return new D3DDevice(adapter, DeviceCreationFlags.None,
-                new[]
-                {
-                    FeatureLevel.Level_12_1, FeatureLevel.Level_12_0, FeatureLevel.Level_11_1,
-                    FeatureLevel.Level_11_0, FeatureLevel.Level_10_0, FeatureLevel.Level_9_3,
-                    FeatureLevel.Level_9_2, FeatureLevel.Level_9_1,
-                });
+            D3DFeatureLevel.Level121,
+            D3DFeatureLevel.Level120,
+            D3DFeatureLevel.Level111,
+            D3DFeatureLevel.Level110,
+            D3DFeatureLevel.Level100,
+            D3DFeatureLevel.Level93,
+            D3DFeatureLevel.Level92,
+            D3DFeatureLevel.Level91
+        };
+
+        ComPtr<ID3D11Device> device = default;
+        ComPtr<ID3D11DeviceContext> context = default;
+        D3DFeatureLevel actualFeatureLevel;
+        ThrowHResult(d3d11.CreateDevice(
+            adapter,
+            D3DDriverType.Unknown,
+            IntPtr.Zero,
+            0u,
+            featureLevels,
+            featureLevelCount,
+            D3D11.SdkVersion,
+            device.GetAddressOf(),
+            &actualFeatureLevel,
+            context.GetAddressOf()));
+
+        return device;
+    }
+
+    private static unsafe ComPtr<IDXGIAdapter> GetAdapterByLuid(ComPtr<IDXGIFactory1> factory, Luid luid)
+    {
+        var index = 0u;
+        ComPtr<IDXGIAdapter> adapter = default;
+
+        while (factory.EnumAdapters(index, adapter.GetAddressOf()) != DxgiErrorNotFound)
+        {
+            AdapterDesc adapterDesc;
+            if (adapter.GetDesc(&adapterDesc) == 0 & AreLuidsEqual(adapterDesc.AdapterLuid, luid))
+                return adapter;
+
+            adapter.Dispose();
+            ++index;
         }
         }
 
 
         throw new ArgumentException("Device with the corresponding LUID not found");
         throw new ArgumentException("Device with the corresponding LUID not found");
     }
     }
 
 
-    public static Texture2D CreateMemoryHandle(D3DDevice device, PixelSize size, Silk.NET.Vulkan.Format format)
+    public static unsafe ComPtr<ID3D11Texture2D> CreateMemoryHandle(ComPtr<ID3D11Device> device, PixelSize size, VulkanFormat format)
     {
     {
-        if (format != Silk.NET.Vulkan.Format.R8G8B8A8Unorm)
+        if (format != VulkanFormat.R8G8B8A8Unorm)
             throw new ArgumentException("Not supported format");
             throw new ArgumentException("Not supported format");
-        return new Texture2D(device,
-            new Texture2DDescription
-            {
-                Format = Format.R8G8B8A8_UNorm,
-                Width = size.Width,
-                Height = size.Height,
-                ArraySize = 1,
-                MipLevels = 1,
-                SampleDescription = new SampleDescription { Count = 1, Quality = 0 },
-                CpuAccessFlags = default,
-                OptionFlags = ResourceOptionFlags.SharedKeyedmutex|ResourceOptionFlags.SharedNthandle,
-                BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource
-            });
+
+        ComPtr<ID3D11Texture2D> texture = default;
+        var textureDesc = new Texture2DDesc
+        {
+            Format = Format.FormatR8G8B8A8Unorm,
+            Width = (uint)size.Width,
+            Height = (uint)size.Height,
+            ArraySize = 1,
+            MipLevels = 1,
+            SampleDesc = new SampleDesc(1, 0),
+            Usage = Usage.Default,
+            BindFlags = (uint)(BindFlag.RenderTarget | BindFlag.ShaderResource),
+            CPUAccessFlags = 0,
+            MiscFlags = (uint)(ResourceMiscFlag.SharedKeyedmutex | ResourceMiscFlag.SharedNthandle)
+        };
+        ThrowHResult(device.CreateTexture2D(&textureDesc, (SubresourceData*)null, texture.GetAddressOf()));
+
+        return texture;
     }
     }
+
+    private static bool AreLuidsEqual(Luid x, Luid y)
+        => x.Low == y.Low && x.High == y.High;
 }
 }

+ 2 - 2
samples/GpuInterop/VulkanDemo/VulkanBufferHelper.cs

@@ -25,7 +25,7 @@ static class VulkanBufferHelper
             Usage = bufferUsageFlags,
             Usage = bufferUsageFlags,
             SharingMode = SharingMode.Exclusive
             SharingMode = SharingMode.Exclusive
         };
         };
-        api.CreateBuffer(device, bufferInfo, null, out buffer).ThrowOnError();
+        api.CreateBuffer(device, in bufferInfo, null, out buffer).ThrowOnError();
 
 
         api.GetBufferMemoryRequirements(device, buffer, out var memoryRequirements);
         api.GetBufferMemoryRequirements(device, buffer, out var memoryRequirements);
 
 
@@ -42,7 +42,7 @@ static class VulkanBufferHelper
                 MemoryPropertyFlags.HostVisibleBit)
                 MemoryPropertyFlags.HostVisibleBit)
         };
         };
 
 
-        api.AllocateMemory(device, memoryAllocateInfo, null, out memory).ThrowOnError();
+        api.AllocateMemory(device, in memoryAllocateInfo, null, out memory).ThrowOnError();
         api.BindBufferMemory(device, buffer, memory, 0);
         api.BindBufferMemory(device, buffer, memory, 0);
         UpdateBufferMemory(vk, memory, initialData);
         UpdateBufferMemory(vk, memory, initialData);
     }
     }

+ 10 - 8
samples/GpuInterop/VulkanDemo/VulkanCommandBufferPool.cs

@@ -28,7 +28,7 @@ namespace Avalonia.Vulkan
                 QueueFamilyIndex = queueFamilyIndex
                 QueueFamilyIndex = queueFamilyIndex
             };
             };
 
 
-            _api.CreateCommandPool(_device, commandPoolCreateInfo, null, out _commandPool)
+            _api.CreateCommandPool(_device, in commandPoolCreateInfo, null, out _commandPool)
                 .ThrowOnError();
                 .ThrowOnError();
         }
         }
 
 
@@ -53,7 +53,7 @@ namespace Avalonia.Vulkan
 
 
             lock (_lock)
             lock (_lock)
             {
             {
-                _api.AllocateCommandBuffers(_device, commandBufferAllocateInfo, out var commandBuffer);
+                _api.AllocateCommandBuffers(_device, in commandBufferAllocateInfo, out var commandBuffer);
 
 
                 return commandBuffer;
                 return commandBuffer;
             }
             }
@@ -111,15 +111,16 @@ namespace Avalonia.Vulkan
                     Flags = FenceCreateFlags.SignaledBit
                     Flags = FenceCreateFlags.SignaledBit
                 };
                 };
 
 
-                api.CreateFence(device, fenceCreateInfo, null, out _fence);
+                api.CreateFence(device, in fenceCreateInfo, null, out _fence);
             }
             }
 
 
             public unsafe void Dispose()
             public unsafe void Dispose()
             {
             {
-                _api.WaitForFences(_device, 1, _fence, true, ulong.MaxValue);
+                _api.WaitForFences(_device, 1, in _fence, true, ulong.MaxValue);
                 lock (_commandBufferPool._lock)
                 lock (_commandBufferPool._lock)
                 {
                 {
-                    _api.FreeCommandBuffers(_device, _commandBufferPool._commandPool, 1, InternalHandle);
+                    var handle = InternalHandle;
+                    _api.FreeCommandBuffers(_device, _commandBufferPool._commandPool, 1, in handle);
                 }
                 }
                 _api.DestroyFence(_device, _fence, null);
                 _api.DestroyFence(_device, _fence, null);
             }
             }
@@ -136,7 +137,7 @@ namespace Avalonia.Vulkan
                         Flags = CommandBufferUsageFlags.OneTimeSubmitBit
                         Flags = CommandBufferUsageFlags.OneTimeSubmitBit
                     };
                     };
 
 
-                    _api.BeginCommandBuffer(InternalHandle, beginInfo);
+                    _api.BeginCommandBuffer(InternalHandle, in beginInfo);
                 }
                 }
             }
             }
 
 
@@ -212,9 +213,10 @@ namespace Avalonia.Vulkan
                             PSignalSemaphores = pSignalSemaphores,
                             PSignalSemaphores = pSignalSemaphores,
                         };
                         };
 
 
-                        _api.ResetFences(_device, 1, fence.Value);
+                        var fenceValue = fence.Value;
+                        _api.ResetFences(_device, 1, in fenceValue);
 
 
-                        _api.QueueSubmit(_queue, 1, submitInfo, fence.Value);
+                        _api.QueueSubmit(_queue, 1, in submitInfo, fenceValue);
                     }
                     }
                 }
                 }
 
 

+ 22 - 21
samples/GpuInterop/VulkanDemo/VulkanContent.cs

@@ -93,7 +93,7 @@ unsafe class VulkanContent : IDisposable
                 PCode = (uint*)ptr,
                 PCode = (uint*)ptr,
             };
             };
 
 
-            api.CreateShaderModule(device, shaderCreateInfo, null, out _vertShader);
+            api.CreateShaderModule(device, in shaderCreateInfo, null, out _vertShader);
         }
         }
 
 
         fixed (byte* ptr = fragShaderData)
         fixed (byte* ptr = fragShaderData)
@@ -105,7 +105,7 @@ unsafe class VulkanContent : IDisposable
                 PCode = (uint*)ptr,
                 PCode = (uint*)ptr,
             };
             };
 
 
-            api.CreateShaderModule(device, shaderCreateInfo, null, out _fragShader);
+            api.CreateShaderModule(device, in shaderCreateInfo, null, out _fragShader);
         }
         }
 
 
         CreateBuffers();
         CreateBuffers();
@@ -160,16 +160,16 @@ unsafe class VulkanContent : IDisposable
 
 
         var commandBufferHandle = new CommandBuffer(commandBuffer.Handle);
         var commandBufferHandle = new CommandBuffer(commandBuffer.Handle);
 
 
-        api.CmdSetViewport(commandBufferHandle, 0, 1,
-            new Viewport()
-            {
-                Width = (float)image.Size.Width,
-                Height = (float)image.Size.Height,
-                MaxDepth = 1,
-                MinDepth = 0,
-                X = 0,
-                Y = 0
-            });
+        var viewport = new Viewport()
+        {
+            Width = (float)image.Size.Width,
+            Height = (float)image.Size.Height,
+            MaxDepth = 1,
+            MinDepth = 0,
+            X = 0,
+            Y = 0
+        };
+        api.CmdSetViewport(commandBufferHandle, 0, 1, in viewport);
 
 
         var scissor = new Rect2D
         var scissor = new Rect2D
         {
         {
@@ -196,7 +196,7 @@ unsafe class VulkanContent : IDisposable
                 PClearValues = clearValue
                 PClearValues = clearValue
             };
             };
 
 
-            api.CmdBeginRenderPass(commandBufferHandle, beginInfo, SubpassContents.Inline);
+            api.CmdBeginRenderPass(commandBufferHandle, in beginInfo, SubpassContents.Inline);
         }
         }
 
 
         api.CmdBindPipeline(commandBufferHandle, PipelineBindPoint.Graphics, _pipeline);
         api.CmdBindPipeline(commandBufferHandle, PipelineBindPoint.Graphics, _pipeline);
@@ -207,7 +207,8 @@ unsafe class VulkanContent : IDisposable
 
 
         api.CmdPushConstants(commandBufferHandle, _pipelineLayout, ShaderStageFlags.VertexBit | ShaderStageFlags.FragmentBit, 0,
         api.CmdPushConstants(commandBufferHandle, _pipelineLayout, ShaderStageFlags.VertexBit | ShaderStageFlags.FragmentBit, 0,
             (uint)Marshal.SizeOf<VertexPushConstant>(), &vertexConstant);
             (uint)Marshal.SizeOf<VertexPushConstant>(), &vertexConstant);
-        api.CmdBindVertexBuffers(commandBufferHandle, 0, 1, _vertexBuffer, 0);
+        var offsets = 0ul;
+        api.CmdBindVertexBuffers(commandBufferHandle, 0, 1, in _vertexBuffer, in offsets);
         api.CmdBindIndexBuffer(commandBufferHandle, _indexBuffer, 0, IndexType.Uint16);
         api.CmdBindIndexBuffer(commandBufferHandle, _indexBuffer, 0, IndexType.Uint16);
 
 
         api.CmdDrawIndexed(commandBufferHandle, (uint)_indices.Length, 1, 0, 0, 0);
         api.CmdDrawIndexed(commandBufferHandle, (uint)_indices.Length, 1, 0, 0, 0);
@@ -250,7 +251,7 @@ unsafe class VulkanContent : IDisposable
 
 
         api.CmdBlitImage(commandBuffer.InternalHandle, _colorAttachment.InternalHandle,
         api.CmdBlitImage(commandBuffer.InternalHandle, _colorAttachment.InternalHandle,
             ImageLayout.TransferSrcOptimal,
             ImageLayout.TransferSrcOptimal,
-            image.InternalHandle, ImageLayout.TransferDstOptimal, 1, srcBlitRegion, Filter.Linear);
+            image.InternalHandle, ImageLayout.TransferDstOptimal, 1, in srcBlitRegion, Filter.Linear);
         
         
         commandBuffer.Submit();
         commandBuffer.Submit();
     }
     }
@@ -341,7 +342,7 @@ unsafe class VulkanContent : IDisposable
         var api = _context.Api;
         var api = _context.Api;
         var device = _context.Device;
         var device = _context.Device;
         api
         api
-            .CreateImage(device, imageCreateInfo, null, out _depthImage).ThrowOnError();
+            .CreateImage(device, in imageCreateInfo, null, out _depthImage).ThrowOnError();
 
 
         api.GetImageMemoryRequirements(device, _depthImage,
         api.GetImageMemoryRequirements(device, _depthImage,
             out var memoryRequirements);
             out var memoryRequirements);
@@ -355,7 +356,7 @@ unsafe class VulkanContent : IDisposable
                 memoryRequirements.MemoryTypeBits, MemoryPropertyFlags.DeviceLocalBit)
                 memoryRequirements.MemoryTypeBits, MemoryPropertyFlags.DeviceLocalBit)
         };
         };
 
 
-        api.AllocateMemory(device, memoryAllocateInfo, null,
+        api.AllocateMemory(device, in memoryAllocateInfo, null,
             out _depthImageMemory).ThrowOnError();
             out _depthImageMemory).ThrowOnError();
 
 
         api.BindImageMemory(device, _depthImage, _depthImageMemory, 0);
         api.BindImageMemory(device, _depthImage, _depthImageMemory, 0);
@@ -380,7 +381,7 @@ unsafe class VulkanContent : IDisposable
         };
         };
 
 
         api
         api
-            .CreateImageView(device, imageViewCreateInfo, null, out _depthImageView)
+            .CreateImageView(device, in imageViewCreateInfo, null, out _depthImageView)
             .ThrowOnError();
             .ThrowOnError();
     }
     }
 
 
@@ -467,7 +468,7 @@ unsafe class VulkanContent : IDisposable
                 PDependencies = &subpassDependency
                 PDependencies = &subpassDependency
             };
             };
 
 
-            api.CreateRenderPass(device, renderPassCreateInfo, null, out _renderPass).ThrowOnError();
+            api.CreateRenderPass(device, in renderPassCreateInfo, null, out _renderPass).ThrowOnError();
 
 
 
 
             // create framebuffer
             // create framebuffer
@@ -486,7 +487,7 @@ unsafe class VulkanContent : IDisposable
                     Layers = 1
                     Layers = 1
                 };
                 };
 
 
-                api.CreateFramebuffer(device, framebufferCreateInfo, null, out _framebuffer).ThrowOnError();
+                api.CreateFramebuffer(device, in framebufferCreateInfo, null, out _framebuffer).ThrowOnError();
             }
             }
         }
         }
 
 
@@ -691,7 +692,7 @@ unsafe class VulkanContent : IDisposable
                         PSetLayouts = &setLayout
                         PSetLayouts = &setLayout
                     };
                     };
 
 
-                    api.CreatePipelineLayout(device, pipelineLayoutCreateInfo, null, out _pipelineLayout)
+                    api.CreatePipelineLayout(device, in pipelineLayoutCreateInfo, null, out _pipelineLayout)
                         .ThrowOnError();
                         .ThrowOnError();
                 }
                 }
 
 

+ 16 - 17
samples/GpuInterop/VulkanDemo/VulkanContext.cs

@@ -9,13 +9,15 @@ using Avalonia.Vulkan;
 using Silk.NET.Core;
 using Silk.NET.Core;
 using Silk.NET.Core.Contexts;
 using Silk.NET.Core.Contexts;
 using Silk.NET.Core.Loader;
 using Silk.NET.Core.Loader;
+using Silk.NET.Core.Native;
+using Silk.NET.Direct3D11;
+using Silk.NET.DXGI;
 using Silk.NET.Vulkan;
 using Silk.NET.Vulkan;
 using Silk.NET.Vulkan.Extensions.EXT;
 using Silk.NET.Vulkan.Extensions.EXT;
 using Silk.NET.Vulkan.Extensions.KHR;
 using Silk.NET.Vulkan.Extensions.KHR;
 using SilkNetDemo;
 using SilkNetDemo;
 using SkiaSharp;
 using SkiaSharp;
-using D3DDevice = SharpDX.Direct3D11.Device;
-#pragma warning disable CS0162 // Unreachable code detected
+
 
 
 namespace GpuInterop.VulkanDemo;
 namespace GpuInterop.VulkanDemo;
 
 
@@ -30,7 +32,7 @@ public unsafe class VulkanContext : IDisposable
     public required VulkanCommandBufferPool Pool { get; init; }
     public required VulkanCommandBufferPool Pool { get; init; }
     public required GRContext? GrContext { get; init; }
     public required GRContext? GrContext { get; init; }
     public required DescriptorPool DescriptorPool { get; init; }
     public required DescriptorPool DescriptorPool { get; init; }
-    public required D3DDevice? D3DDevice { get; init; }
+    public required ComPtr<ID3D11Device> D3DDevice { get; init; }
 
 
     public static (VulkanContext? result, string info) TryCreate(ICompositionGpuInterop gpuInterop)
     public static (VulkanContext? result, string info) TryCreate(ICompositionGpuInterop gpuInterop)
     {
     {
@@ -79,7 +81,8 @@ public unsafe class VulkanContext : IDisposable
             enabledLayers.Clear();
             enabledLayers.Clear();
             using var pRequiredExtensions = new ByteStringList(enabledExtensions);
             using var pRequiredExtensions = new ByteStringList(enabledExtensions);
             using var pEnabledLayers = new ByteStringList(enabledLayers);
             using var pEnabledLayers = new ByteStringList(enabledLayers);
-            api.CreateInstance(new InstanceCreateInfo
+
+            var instanceCreateInfo = new InstanceCreateInfo
             {
             {
                 SType = StructureType.InstanceCreateInfo,
                 SType = StructureType.InstanceCreateInfo,
                 PApplicationInfo = &applicationInfo,
                 PApplicationInfo = &applicationInfo,
@@ -88,7 +91,9 @@ public unsafe class VulkanContext : IDisposable
                 PpEnabledLayerNames = pEnabledLayers,
                 PpEnabledLayerNames = pEnabledLayers,
                 EnabledLayerCount = pEnabledLayers.UCount,
                 EnabledLayerCount = pEnabledLayers.UCount,
                 Flags = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? InstanceCreateFlags.EnumeratePortabilityBitKhr : default
                 Flags = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? InstanceCreateFlags.EnumeratePortabilityBitKhr : default
-            }, null, out var vkInstance).ThrowOnError();
+            };
+
+            api.CreateInstance(in instanceCreateInfo, null, out var vkInstance).ThrowOnError();
 
 
 
 
             if (api.TryGetInstanceExtension(vkInstance, out ExtDebugUtils debugUtils))
             if (api.TryGetInstanceExtension(vkInstance, out ExtDebugUtils debugUtils))
@@ -105,7 +110,7 @@ public unsafe class VulkanContext : IDisposable
                     PfnUserCallback = new PfnDebugUtilsMessengerCallbackEXT(LogCallback),
                     PfnUserCallback = new PfnDebugUtilsMessengerCallbackEXT(LogCallback),
                 };
                 };
 
 
-                debugUtils.CreateDebugUtilsMessenger(vkInstance, debugCreateInfo, null, out _);
+                debugUtils.CreateDebugUtilsMessenger(vkInstance, in debugCreateInfo, null, out _);
             }
             }
 
 
             var requireDeviceExtensions = new List<string>();
             var requireDeviceExtensions = new List<string>();
@@ -273,13 +278,13 @@ public unsafe class VulkanContext : IDisposable
                             return (null, "Can't create Skia GrContext, device is likely broken");
                             return (null, "Can't create Skia GrContext, device is likely broken");
                     }
                     }
 
 
-                    D3DDevice? d3dDevice = null;
+                    ComPtr<ID3D11Device> d3dDevice = null;
                     if (physicalDeviceIDProperties.DeviceLuidvalid &&
                     if (physicalDeviceIDProperties.DeviceLuidvalid &&
                         RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
                         RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
                         !gpuInterop.SupportedImageHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaqueNtHandle)
                         !gpuInterop.SupportedImageHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaqueNtHandle)
                         )
                         )
                         d3dDevice = D3DMemoryHelper.CreateDeviceByLuid(
                         d3dDevice = D3DMemoryHelper.CreateDeviceByLuid(
-                            new Span<byte>(physicalDeviceIDProperties.DeviceLuid, 8));
+                            MemoryMarshal.Read<Luid>(new Span<byte>(physicalDeviceIDProperties.DeviceLuid, 8)));
                     success = true;
                     success = true;
                     return (new VulkanContext
                     return (new VulkanContext
                     {
                     {
@@ -354,20 +359,14 @@ public unsafe class VulkanContext : IDisposable
 
 
 
 
     private const string MacVulkanSdkGlobalPath = "/usr/local/lib/libvulkan.dylib";
     private const string MacVulkanSdkGlobalPath = "/usr/local/lib/libvulkan.dylib";
-    class MacLibraryNameContainer : SearchPathContainer
-    {
-        public override string Windows64 { get; }
-        public override string Windows86 { get; }
-        public override string Linux { get; }
-        public override string MacOS { get; } = MacVulkanSdkGlobalPath;
-    }
+
     private static Vk GetApi()
     private static Vk GetApi()
     {
     {
         if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || !File.Exists(MacVulkanSdkGlobalPath))
         if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || !File.Exists(MacVulkanSdkGlobalPath))
             return Vk.GetApi();
             return Vk.GetApi();
         var ctx = new MultiNativeContext(new INativeContext[2]
         var ctx = new MultiNativeContext(new INativeContext[2]
         {
         {
-            Vk.CreateDefaultContext(new MacLibraryNameContainer().GetLibraryName()),
+            Vk.CreateDefaultContext([MacVulkanSdkGlobalPath]),
             null!
             null!
         });
         });
         var ret = new Vk(ctx);
         var ret = new Vk(ctx);
@@ -383,7 +382,7 @@ public unsafe class VulkanContext : IDisposable
     
     
     public void Dispose()
     public void Dispose()
     {
     {
-        D3DDevice?.Dispose();
+        D3DDevice.Dispose();
         GrContext?.Dispose();
         GrContext?.Dispose();
         Pool.Dispose();
         Pool.Dispose();
         Api.DestroyDescriptorPool(Device, DescriptorPool, null);
         Api.DestroyDescriptorPool(Device, DescriptorPool, null);

+ 32 - 17
samples/GpuInterop/VulkanDemo/VulkanImage.cs

@@ -6,12 +6,15 @@ using System.Runtime.InteropServices;
 using Avalonia;
 using Avalonia;
 using Avalonia.Platform;
 using Avalonia.Platform;
 using Avalonia.Vulkan;
 using Avalonia.Vulkan;
-using SharpDX.DXGI;
+using Silk.NET.Core.Native;
+using Silk.NET.Direct3D11;
+using Silk.NET.DXGI;
 using Silk.NET.Vulkan;
 using Silk.NET.Vulkan;
 using Silk.NET.Vulkan.Extensions.EXT;
 using Silk.NET.Vulkan.Extensions.EXT;
 using Silk.NET.Vulkan.Extensions.KHR;
 using Silk.NET.Vulkan.Extensions.KHR;
 using SilkNetDemo;
 using SilkNetDemo;
 using SkiaSharp;
 using SkiaSharp;
+using static Silk.NET.Core.Native.SilkMarshal;
 using Device = Silk.NET.Vulkan.Device;
 using Device = Silk.NET.Vulkan.Device;
 using Format = Silk.NET.Vulkan.Format;
 using Format = Silk.NET.Vulkan.Format;
 
 
@@ -29,7 +32,7 @@ public unsafe class VulkanImage : IDisposable
         private ImageUsageFlags _imageUsageFlags { get; }
         private ImageUsageFlags _imageUsageFlags { get; }
         private ImageView _imageView { get; set; }
         private ImageView _imageView { get; set; }
         private DeviceMemory _imageMemory { get; set; }
         private DeviceMemory _imageMemory { get; set; }
-        private readonly SharpDX.Direct3D11.Texture2D? _d3dTexture2D;
+        private ComPtr<ID3D11Texture2D> _d3dTexture2D;
         
         
         internal Image InternalHandle { get; private set; }
         internal Image InternalHandle { get; private set; }
         internal Format Format { get; }
         internal Format Format { get; }
@@ -111,7 +114,7 @@ public unsafe class VulkanImage : IDisposable
             };
             };
 
 
             Api
             Api
-                .CreateImage(_device, imageCreateInfo, null, out var image).ThrowOnError();
+                .CreateImage(_device, in imageCreateInfo, null, out var image).ThrowOnError();
             InternalHandle = image;
             InternalHandle = image;
 
 
             if (!exportable || !RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
             if (!exportable || !RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
@@ -135,16 +138,16 @@ public unsafe class VulkanImage : IDisposable
                 ImportMemoryWin32HandleInfoKHR handleImport = default;
                 ImportMemoryWin32HandleInfoKHR handleImport = default;
                 if (handleType == ExternalMemoryHandleTypeFlags.D3D11TextureBit && exportable)
                 if (handleType == ExternalMemoryHandleTypeFlags.D3D11TextureBit && exportable)
                 {
                 {
-                    var d3dDevice = vk.D3DDevice ?? throw new NotSupportedException("Vulkan D3DDevice wasn't created");
-                    _d3dTexture2D = D3DMemoryHelper.CreateMemoryHandle(d3dDevice, size, Format);
-                    using var dxgi = _d3dTexture2D.QueryInterface<SharpDX.DXGI.Resource1>();
+                    if (vk.D3DDevice.Handle == null)
+                        throw new NotSupportedException("Vulkan D3DDevice wasn't created");
+                    _d3dTexture2D = D3DMemoryHelper.CreateMemoryHandle(vk.D3DDevice, size, Format);
 
 
                     handleImport = new ImportMemoryWin32HandleInfoKHR
                     handleImport = new ImportMemoryWin32HandleInfoKHR
                     {
                     {
                         PNext = &dedicatedAllocation,
                         PNext = &dedicatedAllocation,
                         SType = StructureType.ImportMemoryWin32HandleInfoKhr,
                         SType = StructureType.ImportMemoryWin32HandleInfoKhr,
                         HandleType = ExternalMemoryHandleTypeFlags.D3D11TextureBit,
                         HandleType = ExternalMemoryHandleTypeFlags.D3D11TextureBit,
-                        Handle = dxgi.CreateSharedHandle(null, SharedResourceFlags.Read | SharedResourceFlags.Write),
+                        Handle = CreateDxgiSharedHandle()
                     };
                     };
                 }
                 }
 
 
@@ -160,7 +163,7 @@ public unsafe class VulkanImage : IDisposable
                         memoryRequirements.MemoryTypeBits, MemoryPropertyFlags.DeviceLocalBit)
                         memoryRequirements.MemoryTypeBits, MemoryPropertyFlags.DeviceLocalBit)
                 };
                 };
 
 
-                Api.AllocateMemory(_device, memoryAllocateInfo, null,
+                Api.AllocateMemory(_device, in memoryAllocateInfo, null,
                     out var imageMemory).ThrowOnError();
                     out var imageMemory).ThrowOnError();
 
 
                 _imageMemory = imageMemory;
                 _imageMemory = imageMemory;
@@ -192,7 +195,7 @@ public unsafe class VulkanImage : IDisposable
             };
             };
 
 
             Api
             Api
-                .CreateImageView(_device, imageViewCreateInfo, null, out var imageView)
+                .CreateImageView(_device, in imageViewCreateInfo, null, out var imageView)
                 .ThrowOnError();
                 .ThrowOnError();
 
 
             _imageView = imageView;
             _imageView = imageView;
@@ -202,6 +205,20 @@ public unsafe class VulkanImage : IDisposable
             TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.NoneKhr);
             TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.NoneKhr);
         }
         }
 
 
+        private IntPtr CreateDxgiSharedHandle()
+        {
+            using var dxgiResource = _d3dTexture2D.QueryInterface<IDXGIResource1>();
+
+            void* sharedHandle;
+            ThrowHResult(dxgiResource.CreateSharedHandle(
+                (SecurityAttributes*) null,
+                DXGI.SharedResourceRead | DXGI.SharedResourceWrite,
+                (char*)null,
+                &sharedHandle));
+
+            return (IntPtr)sharedHandle;
+        }
+
         public int ExportFd()
         public int ExportFd()
         {
         {
             if (!Api.TryGetDeviceExtension<KhrExternalMemoryFd>(_instance, _device, out var ext))
             if (!Api.TryGetDeviceExtension<KhrExternalMemoryFd>(_instance, _device, out var ext))
@@ -212,7 +229,7 @@ public unsafe class VulkanImage : IDisposable
                 SType = StructureType.MemoryGetFDInfoKhr,
                 SType = StructureType.MemoryGetFDInfoKhr,
                 HandleType = ExternalMemoryHandleTypeFlags.OpaqueFDBit
                 HandleType = ExternalMemoryHandleTypeFlags.OpaqueFDBit
             };
             };
-            ext.GetMemoryF(_device, info, out var fd).ThrowOnError();
+            ext.GetMemoryF(_device, in info, out var fd).ThrowOnError();
             return fd;
             return fd;
         }
         }
         
         
@@ -226,7 +243,7 @@ public unsafe class VulkanImage : IDisposable
                 SType = StructureType.MemoryGetWin32HandleInfoKhr,
                 SType = StructureType.MemoryGetWin32HandleInfoKhr,
                 HandleType = ExternalMemoryHandleTypeFlags.OpaqueWin32Bit
                 HandleType = ExternalMemoryHandleTypeFlags.OpaqueWin32Bit
             };
             };
-            ext.GetMemoryWin32Handle(_device, info, out var fd).ThrowOnError();
+            ext.GetMemoryWin32Handle(_device, in info, out var fd).ThrowOnError();
             return fd;
             return fd;
         }
         }
 
 
@@ -254,11 +271,10 @@ public unsafe class VulkanImage : IDisposable
         {
         {
             if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
             if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
             {
             {
-                if (_d3dTexture2D != null)
+                if (_d3dTexture2D.Handle != null)
                 {
                 {
-                    using var dxgi = _d3dTexture2D!.QueryInterface<Resource1>();
                     return new PlatformHandle(
                     return new PlatformHandle(
-                        dxgi.CreateSharedHandle(null, SharedResourceFlags.Read | SharedResourceFlags.Write),
+                        CreateDxgiSharedHandle(),
                         KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureNtHandle);
                         KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureNtHandle);
                 }
                 }
 
 
@@ -275,7 +291,7 @@ public unsafe class VulkanImage : IDisposable
 
 
         public ImageTiling Tiling => ImageTiling.Optimal;
         public ImageTiling Tiling => ImageTiling.Optimal;
 
 
-        public bool IsDirectXBacked => _d3dTexture2D != null;
+        public bool IsDirectXBacked => _d3dTexture2D.Handle != null;
         
         
         internal void TransitionLayout(CommandBuffer commandBuffer,
         internal void TransitionLayout(CommandBuffer commandBuffer,
             ImageLayout fromLayout, AccessFlags fromAccessFlags,
             ImageLayout fromLayout, AccessFlags fromAccessFlags,
@@ -367,8 +383,7 @@ public unsafe class VulkanImage : IDisposable
                 }
                 }
             };
             };
 
 
-            using (var backendTexture = new GRBackendRenderTarget(_image.Size.Width, _image.Size.Height, 1,
-                       imageInfo))
+            using (var backendTexture = new GRBackendRenderTarget(_image.Size.Width, _image.Size.Height, imageInfo))
             using (var surface = SKSurface.Create(_vk.GrContext, backendTexture,
             using (var surface = SKSurface.Create(_vk.GrContext, backendTexture,
                        GRSurfaceOrigin.TopLeft,
                        GRSurfaceOrigin.TopLeft,
                        SKColorType.Rgba8888, SKColorSpace.CreateSrgb()))
                        SKColorType.Rgba8888, SKColorSpace.CreateSrgb()))

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

@@ -54,6 +54,6 @@ internal static class VulkanMemoryHelper
             0,
             0,
             null,
             null,
             1,
             1,
-            barrier);
+            in barrier);
     }
     }
 }
 }

+ 4 - 4
samples/GpuInterop/VulkanDemo/VulkanSemaphorePair.cs

@@ -29,10 +29,10 @@ class VulkanSemaphorePair : IDisposable
             PNext = exportable ? &semaphoreExportInfo : null
             PNext = exportable ? &semaphoreExportInfo : null
         };
         };
 
 
-        resources.Api.CreateSemaphore(resources.Device, semaphoreCreateInfo, null, out var semaphore).ThrowOnError();
+        resources.Api.CreateSemaphore(resources.Device, in semaphoreCreateInfo, null, out var semaphore).ThrowOnError();
         ImageAvailableSemaphore = semaphore;
         ImageAvailableSemaphore = semaphore;
 
 
-        resources.Api.CreateSemaphore(resources.Device, semaphoreCreateInfo, null, out semaphore).ThrowOnError();
+        resources.Api.CreateSemaphore(resources.Device, in semaphoreCreateInfo, null, out semaphore).ThrowOnError();
         RenderFinishedSemaphore = semaphore;
         RenderFinishedSemaphore = semaphore;
     }
     }
 
 
@@ -47,7 +47,7 @@ class VulkanSemaphorePair : IDisposable
             Semaphore = renderFinished ? RenderFinishedSemaphore : ImageAvailableSemaphore,
             Semaphore = renderFinished ? RenderFinishedSemaphore : ImageAvailableSemaphore,
             HandleType = ExternalSemaphoreHandleTypeFlags.OpaqueFDBit
             HandleType = ExternalSemaphoreHandleTypeFlags.OpaqueFDBit
         };
         };
-        ext.GetSemaphoreF(_resources.Device, info, out var fd).ThrowOnError();
+        ext.GetSemaphoreF(_resources.Device, in info, out var fd).ThrowOnError();
         return fd;
         return fd;
     }
     }
     
     
@@ -62,7 +62,7 @@ class VulkanSemaphorePair : IDisposable
             Semaphore = renderFinished ? RenderFinishedSemaphore : ImageAvailableSemaphore,
             Semaphore = renderFinished ? RenderFinishedSemaphore : ImageAvailableSemaphore,
             HandleType = ExternalSemaphoreHandleTypeFlags.OpaqueWin32Bit
             HandleType = ExternalSemaphoreHandleTypeFlags.OpaqueWin32Bit
         };
         };
-        ext.GetSemaphoreWin32Handle(_resources.Device, info, out var fd).ThrowOnError();
+        ext.GetSemaphoreWin32Handle(_resources.Device, in info, out var fd).ThrowOnError();
         return fd;
         return fd;
     }
     }
 
 

+ 4 - 4
samples/GpuInterop/VulkanDemo/VulkanSwapchain.cs

@@ -119,7 +119,7 @@ class VulkanSwapchainImage : ISwapchainImage
             buffer.Submit();
             buffer.Submit();
         }
         }
         else
         else
-            buffer.Submit(new[] { _semaphorePair.ImageAvailableSemaphore },
+            buffer.Submit(new[] { _semaphorePair!.ImageAvailableSemaphore },
                 new[]
                 new[]
                 {
                 {
                     PipelineStageFlags.AllGraphicsBit
                     PipelineStageFlags.AllGraphicsBit
@@ -160,7 +160,7 @@ class VulkanSwapchainImage : ISwapchainImage
             }
             }
         }
         }
         else
         else
-            buffer.Submit(null, null, new[] { _semaphorePair.RenderFinishedSemaphore });
+            buffer.Submit(null, null, new[] { _semaphorePair!.RenderFinishedSemaphore });
 
 
         if (_timelineSemaphore != null)
         if (_timelineSemaphore != null)
         {
         {
@@ -168,9 +168,9 @@ class VulkanSwapchainImage : ISwapchainImage
         }
         }
         else if (!_image.IsDirectXBacked)
         else if (!_image.IsDirectXBacked)
         {
         {
-            _availableSemaphore ??= _interop.ImportSemaphore(_semaphorePair.Export(false));
+            _availableSemaphore ??= _interop.ImportSemaphore(_semaphorePair!.Export(false));
             
             
-            _renderCompletedSemaphore ??= _interop.ImportSemaphore(_semaphorePair.Export(true));
+            _renderCompletedSemaphore ??= _interop.ImportSemaphore(_semaphorePair!.Export(true));
         }
         }
 
 
         _importedImage ??= _interop.ImportImage(_image.Export(),
         _importedImage ??= _interop.ImportImage(_image.Export(),

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

@@ -32,7 +32,7 @@ class VulkanTimelineSemaphore : IDisposable
             SType = StructureType.SemaphoreCreateInfo,
             SType = StructureType.SemaphoreCreateInfo,
             PNext = &semaphoreTypeInfo,
             PNext = &semaphoreTypeInfo,
         };
         };
-        resources.Api.CreateSemaphore(resources.Device, semaphoreCreateInfo, null, out var semaphore).ThrowOnError();
+        resources.Api.CreateSemaphore(resources.Device, in semaphoreCreateInfo, null, out var semaphore).ThrowOnError();
         Handle = semaphore;
         Handle = semaphore;
     }
     }