diff --git a/Avalonia.Desktop.slnf b/Avalonia.Desktop.slnf
index 465e579a44..799e920441 100644
--- a/Avalonia.Desktop.slnf
+++ b/Avalonia.Desktop.slnf
@@ -30,6 +30,7 @@
"src\\Avalonia.MicroCom\\Avalonia.MicroCom.csproj",
"src\\Avalonia.Native\\Avalonia.Native.csproj",
"src\\Avalonia.OpenGL\\Avalonia.OpenGL.csproj",
+ "src\\Avalonia.Vulkan\\Avalonia.Vulkan.csproj",
"src\\Avalonia.ReactiveUI\\Avalonia.ReactiveUI.csproj",
"src\\Avalonia.Remote.Protocol\\Avalonia.Remote.Protocol.csproj",
"src\\Avalonia.Themes.Fluent\\Avalonia.Themes.Fluent.csproj",
diff --git a/Avalonia.sln b/Avalonia.sln
index 88a43802a8..2ebd2550ae 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -298,6 +298,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnloadableAssemblyLoadConte
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnloadableAssemblyLoadContextPlug", "samples\UnloadableAssemblyLoadContext\UnloadableAssemblyLoadContextPlug\UnloadableAssemblyLoadContextPlug.csproj", "{DA5F1FF9-4259-4C54-B443-85CFA226EE6A}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Vulkan", "src\Avalonia.Vulkan\Avalonia.Vulkan.csproj", "{3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}"
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.RenderTests.WpfCompare", "tests\Avalonia.RenderTests.WpfCompare\Avalonia.RenderTests.WpfCompare.csproj", "{9AE1B827-21AC-4063-AB22-C8804B7F931E}"
EndProject
Global
@@ -676,6 +678,10 @@ Global
{60B4ED1F-ECFA-453B-8A70-1788261C8355}.Debug|Any CPU.Build.0 = Debug|Any CPU
{60B4ED1F-ECFA-453B-8A70-1788261C8355}.Release|Any CPU.ActiveCfg = Release|Any CPU
{60B4ED1F-ECFA-453B-8A70-1788261C8355}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}.Release|Any CPU.Build.0 = Release|Any CPU
{B0FD6A48-FBAB-4676-B36A-DE76B0922B12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B0FD6A48-FBAB-4676-B36A-DE76B0922B12}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0FD6A48-FBAB-4676-B36A-DE76B0922B12}.Release|Any CPU.ActiveCfg = Release|Any CPU
diff --git a/Avalonia.sln.DotSettings b/Avalonia.sln.DotSettings
index 52f687ffab..cc58566622 100644
--- a/Avalonia.sln.DotSettings
+++ b/Avalonia.sln.DotSettings
@@ -39,4 +39,5 @@
True
True
True
- True
+ True
+ True
diff --git a/build/CoreLibraries.props b/build/CoreLibraries.props
index a9af587a45..43ab0fbab2 100644
--- a/build/CoreLibraries.props
+++ b/build/CoreLibraries.props
@@ -5,6 +5,7 @@
+
diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs
index b3372ee0f8..036dd13f7a 100644
--- a/samples/ControlCatalog.NetCore/Program.cs
+++ b/samples/ControlCatalog.NetCore/Program.cs
@@ -13,7 +13,7 @@ using Avalonia.LinuxFramebuffer.Output;
using Avalonia.LogicalTree;
using Avalonia.Rendering.Composition;
using Avalonia.Threading;
-
+using Avalonia.Vulkan;
using ControlCatalog.Pages;
namespace ControlCatalog.NetCore
@@ -133,7 +133,15 @@ namespace ControlCatalog.NetCore
{
EnableMultiTouch = true,
UseDBusMenu = true,
- EnableIme = true
+ EnableIme = true,
+ })
+
+ .With(new VulkanOptions
+ {
+ VulkanInstanceCreationOptions = new ()
+ {
+ UseDebug = true
+ }
})
.With(new CompositionOptions()
{
diff --git a/samples/GpuInterop/Program.cs b/samples/GpuInterop/Program.cs
index 8d7ccf4866..e07780f80b 100644
--- a/samples/GpuInterop/Program.cs
+++ b/samples/GpuInterop/Program.cs
@@ -1,5 +1,8 @@
global using System.Reactive.Disposables;
using Avalonia;
+using Avalonia.Logging;
+using Avalonia.Vulkan;
+
namespace GpuInterop
{
public class Program
@@ -10,6 +13,21 @@ namespace GpuInterop
public static AppBuilder BuildAvaloniaApp() =>
AppBuilder.Configure()
.UsePlatformDetect()
- .LogToTrace();
+ .With(new Win32PlatformOptions
+ {
+ RenderingMode = new []
+ {
+ Win32RenderingMode.Vulkan
+ }
+ })
+ .With(new X11PlatformOptions(){RenderingMode =new[] { X11RenderingMode.Vulkan } })
+ .With(new VulkanOptions()
+ {
+ VulkanInstanceCreationOptions = new VulkanInstanceCreationOptions()
+ {
+ UseDebug = true
+ }
+ })
+ .LogToTrace(LogEventLevel.Debug, "Vulkan");
}
}
diff --git a/samples/GpuInterop/VulkanDemo/VulkanContent.cs b/samples/GpuInterop/VulkanDemo/VulkanContent.cs
index fe95db00f4..576c34e837 100644
--- a/samples/GpuInterop/VulkanDemo/VulkanContent.cs
+++ b/samples/GpuInterop/VulkanDemo/VulkanContent.cs
@@ -397,7 +397,7 @@ unsafe class VulkanContent : IDisposable
Matrix4x4.CreatePerspectiveFieldOfView((float)(Math.PI / 4), (float)size.Width / size.Height,
0.01f, 1000);
- _colorAttachment = new VulkanImage(_context, (uint)Format.R8G8B8A8Unorm, size, false);
+ _colorAttachment = new VulkanImage(_context, (uint)Format.R8G8B8A8Unorm, size, false, Array.Empty());
CreateDepthAttachment(size);
var api = _context.Api;
diff --git a/samples/GpuInterop/VulkanDemo/VulkanContext.cs b/samples/GpuInterop/VulkanDemo/VulkanContext.cs
index 0983a373f3..6983a69d86 100644
--- a/samples/GpuInterop/VulkanDemo/VulkanContext.cs
+++ b/samples/GpuInterop/VulkanDemo/VulkanContext.cs
@@ -101,8 +101,10 @@ public unsafe class VulkanContext : IDisposable
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
- if (!gpuInterop.SupportedImageHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes
+ if (!(gpuInterop.SupportedImageHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes
.D3D11TextureGlobalSharedHandle)
+ || gpuInterop.SupportedImageHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes
+ .VulkanOpaqueNtHandle))
)
return (null, "Image sharing is not supported by the current backend");
requireDeviceExtensions.Add(KhrExternalMemoryWin32.ExtensionName);
@@ -240,10 +242,13 @@ public unsafe class VulkanContext : IDisposable
}
});
+
D3DDevice? d3dDevice = null;
if (physicalDeviceIDProperties.DeviceLuidvalid &&
- RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
+ !gpuInterop.SupportedImageHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaqueNtHandle)
+ )
d3dDevice = D3DMemoryHelper.CreateDeviceByLuid(
new Span(physicalDeviceIDProperties.DeviceLuid, 8));
diff --git a/samples/GpuInterop/VulkanDemo/VulkanImage.cs b/samples/GpuInterop/VulkanDemo/VulkanImage.cs
index a385468b26..ea43441243 100644
--- a/samples/GpuInterop/VulkanDemo/VulkanImage.cs
+++ b/samples/GpuInterop/VulkanDemo/VulkanImage.cs
@@ -1,5 +1,7 @@
using System;
+using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Runtime.InteropServices;
using Avalonia;
using Avalonia.Platform;
@@ -44,7 +46,7 @@ public unsafe class VulkanImage : IDisposable
public uint CurrentLayout => (uint) _currentLayout;
public VulkanImage(VulkanContext vk, uint format, PixelSize size,
- bool exportable, uint mipLevels = 0)
+ bool exportable, IReadOnlyList supportedHandleTypes)
{
_vk = vk;
_instance = vk.Instance;
@@ -62,8 +64,12 @@ 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.D3D11TextureBit :
+ (supportedHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureNtHandle)
+ && !supportedHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaqueNtHandle) ?
+ ExternalMemoryHandleTypeFlags.D3D11TextureBit :
+ ExternalMemoryHandleTypeFlags.OpaqueWin32Bit) :
ExternalMemoryHandleTypeFlags.OpaqueFDBit;
+
var externalMemoryCreateInfo = new ExternalMemoryImageCreateInfo
{
SType = StructureType.ExternalMemoryImageCreateInfo,
@@ -96,35 +102,37 @@ public unsafe class VulkanImage : IDisposable
Api.GetImageMemoryRequirements(_device, InternalHandle,
out var memoryRequirements);
-
- var fdExport = new ExportMemoryAllocateInfo
- {
- HandleTypes = handleType, SType = StructureType.ExportMemoryAllocateInfo
- };
var dedicatedAllocation = new MemoryDedicatedAllocateInfoKHR
{
SType = StructureType.MemoryDedicatedAllocateInfoKhr,
Image = image
};
+
+ var fdExport = new ExportMemoryAllocateInfo
+ {
+ HandleTypes = handleType, SType = StructureType.ExportMemoryAllocateInfo,
+ PNext = &dedicatedAllocation
+ };
+
ImportMemoryWin32HandleInfoKHR handleImport = default;
- if (exportable && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ if (handleType == ExternalMemoryHandleTypeFlags.D3D11TextureBit && exportable)
{
- _d3dTexture2D = D3DMemoryHelper.CreateMemoryHandle(vk.D3DDevice!, size, Format);
- using var dxgi = _d3dTexture2D.QueryInterface();
-
- handleImport = new ImportMemoryWin32HandleInfoKHR
- {
- PNext = &dedicatedAllocation,
- SType = StructureType.ImportMemoryWin32HandleInfoKhr,
- HandleType = ExternalMemoryHandleTypeFlags.D3D11TextureBit,
- Handle = dxgi.CreateSharedHandle(null, SharedResourceFlags.Read | SharedResourceFlags.Write),
- };
+ _d3dTexture2D = D3DMemoryHelper.CreateMemoryHandle(vk.D3DDevice, size, Format);
+ using var dxgi = _d3dTexture2D.QueryInterface();
+
+ handleImport = new ImportMemoryWin32HandleInfoKHR
+ {
+ PNext = &dedicatedAllocation,
+ SType = StructureType.ImportMemoryWin32HandleInfoKhr,
+ HandleType = ExternalMemoryHandleTypeFlags.D3D11TextureBit,
+ Handle = dxgi.CreateSharedHandle(null, SharedResourceFlags.Read | SharedResourceFlags.Write),
+ };
}
var memoryAllocateInfo = new MemoryAllocateInfo
{
PNext =
- exportable ? RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? &handleImport : &fdExport : null,
+ exportable ? handleImport.Handle != IntPtr.Zero ? &handleImport : &fdExport : null,
SType = StructureType.MemoryAllocateInfo,
AllocationSize = memoryRequirements.Size,
MemoryTypeIndex = (uint)VulkanMemoryHelper.FindSuitableMemoryTypeIndex(
@@ -187,14 +195,34 @@ public unsafe class VulkanImage : IDisposable
return fd;
}
+ public IntPtr ExportOpaqueNtHandle()
+ {
+ if (!Api.TryGetDeviceExtension(_instance, _device, out var ext))
+ throw new InvalidOperationException();
+ var info = new MemoryGetWin32HandleInfoKHR()
+ {
+ Memory = _imageMemory,
+ SType = StructureType.MemoryGetWin32HandleInfoKhr,
+ HandleType = ExternalMemoryHandleTypeFlags.OpaqueWin32Bit
+ };
+ ext.GetMemoryWin32Handle(_device, info, out var fd).ThrowOnError();
+ return fd;
+ }
+
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);
+ if (_d3dTexture2D != null)
+ {
+ using var dxgi = _d3dTexture2D!.QueryInterface();
+ return new PlatformHandle(
+ dxgi.CreateSharedHandle(null, SharedResourceFlags.Read | SharedResourceFlags.Write),
+ KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureNtHandle);
+ }
+
+ return new PlatformHandle(ExportOpaqueNtHandle(),
+ KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaqueNtHandle);
}
else
return new PlatformHandle(new IntPtr(ExportFd()),
@@ -203,7 +231,7 @@ public unsafe class VulkanImage : IDisposable
public ImageTiling Tiling => ImageTiling.Optimal;
-
+ public bool IsDirectXBacked => _d3dTexture2D != null;
internal void TransitionLayout(CommandBuffer commandBuffer,
ImageLayout fromLayout, AccessFlags fromAccessFlags,
diff --git a/samples/GpuInterop/VulkanDemo/VulkanSemaphorePair.cs b/samples/GpuInterop/VulkanDemo/VulkanSemaphorePair.cs
index 279c313a27..163a39dd9e 100644
--- a/samples/GpuInterop/VulkanDemo/VulkanSemaphorePair.cs
+++ b/samples/GpuInterop/VulkanDemo/VulkanSemaphorePair.cs
@@ -1,4 +1,6 @@
using System;
+using System.Runtime.InteropServices;
+using Avalonia.Platform;
using Silk.NET.Vulkan;
using Silk.NET.Vulkan.Extensions.KHR;
using SilkNetDemo;
@@ -16,7 +18,9 @@ class VulkanSemaphorePair : IDisposable
var semaphoreExportInfo = new ExportSemaphoreCreateInfo
{
SType = StructureType.ExportSemaphoreCreateInfo,
- HandleTypes = ExternalSemaphoreHandleTypeFlags.OpaqueFDBit
+ HandleTypes = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
+ ExternalSemaphoreHandleTypeFlags.OpaqueWin32Bit :
+ ExternalSemaphoreHandleTypeFlags.OpaqueFDBit
};
var semaphoreCreateInfo = new SemaphoreCreateInfo
@@ -46,6 +50,30 @@ class VulkanSemaphorePair : IDisposable
ext.GetSemaphoreF(_resources.Device, info, out var fd).ThrowOnError();
return fd;
}
+
+ public IntPtr ExportWin32(bool renderFinished)
+ {
+ if (!_resources.Api.TryGetDeviceExtension(_resources.Instance, _resources.Device,
+ out var ext))
+ throw new InvalidOperationException();
+ var info = new SemaphoreGetWin32HandleInfoKHR()
+ {
+ SType = StructureType.SemaphoreGetWin32HandleInfoKhr,
+ Semaphore = renderFinished ? RenderFinishedSemaphore : ImageAvailableSemaphore,
+ HandleType = ExternalSemaphoreHandleTypeFlags.OpaqueWin32Bit
+ };
+ ext.GetSemaphoreWin32Handle(_resources.Device, info, out var fd).ThrowOnError();
+ return fd;
+ }
+
+ public IPlatformHandle Export(bool renderFinished)
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ return new PlatformHandle(ExportWin32(renderFinished),
+ KnownPlatformGraphicsExternalSemaphoreHandleTypes.VulkanOpaqueNtHandle);
+ return new PlatformHandle(new IntPtr(ExportFd(renderFinished)),
+ KnownPlatformGraphicsExternalSemaphoreHandleTypes.VulkanOpaquePosixFileDescriptor);
+ }
internal Semaphore ImageAvailableSemaphore { get; }
internal Semaphore RenderFinishedSemaphore { get; }
@@ -55,4 +83,4 @@ class VulkanSemaphorePair : IDisposable
_resources.Api.DestroySemaphore(_resources.Device, ImageAvailableSemaphore, null);
_resources.Api.DestroySemaphore(_resources.Device, RenderFinishedSemaphore, null);
}
-}
\ No newline at end of file
+}
diff --git a/samples/GpuInterop/VulkanDemo/VulkanSwapchain.cs b/samples/GpuInterop/VulkanDemo/VulkanSwapchain.cs
index cd026b3972..a748ba4bb6 100644
--- a/samples/GpuInterop/VulkanDemo/VulkanSwapchain.cs
+++ b/samples/GpuInterop/VulkanDemo/VulkanSwapchain.cs
@@ -52,7 +52,7 @@ class VulkanSwapchainImage : ISwapchainImage
_interop = interop;
_target = target;
Size = size;
- _image = new VulkanImage(vk, (uint)Format.R8G8B8A8Unorm, size, true);
+ _image = new VulkanImage(vk, (uint)Format.R8G8B8A8Unorm, size, true, interop.SupportedImageHandleTypes);
_semaphorePair = new VulkanSemaphorePair(vk, true);
}
@@ -83,7 +83,7 @@ class VulkanSwapchainImage : ISwapchainImage
ImageLayout.Undefined, AccessFlags.None,
ImageLayout.ColorAttachmentOptimal, AccessFlags.ColorAttachmentReadBit);
- if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ if(_image.IsDirectXBacked)
buffer.Submit(null,null,null, null, new VulkanCommandBufferPool.VulkanCommandBuffer.KeyedMutexSubmitInfo
{
AcquireKey = 0,
@@ -111,8 +111,7 @@ class VulkanSwapchainImage : ISwapchainImage
_image.TransitionLayout(buffer.InternalHandle, ImageLayout.TransferSrcOptimal, AccessFlags.TransferWriteBit);
-
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ if (_image.IsDirectXBacked)
{
buffer.Submit(null, null, null, null,
new VulkanCommandBufferPool.VulkanCommandBuffer.KeyedMutexSubmitInfo
@@ -123,15 +122,11 @@ class VulkanSwapchainImage : ISwapchainImage
else
buffer.Submit(null, null, new[] { _semaphorePair.RenderFinishedSemaphore });
- if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ if (!_image.IsDirectXBacked)
{
- _availableSemaphore ??= _interop.ImportSemaphore(new PlatformHandle(
- new IntPtr(_semaphorePair.ExportFd(false)),
- KnownPlatformGraphicsExternalSemaphoreHandleTypes.VulkanOpaquePosixFileDescriptor));
+ _availableSemaphore ??= _interop.ImportSemaphore(_semaphorePair.Export(false));
- _renderCompletedSemaphore ??= _interop.ImportSemaphore(new PlatformHandle(
- new IntPtr(_semaphorePair.ExportFd(true)),
- KnownPlatformGraphicsExternalSemaphoreHandleTypes.VulkanOpaquePosixFileDescriptor));
+ _renderCompletedSemaphore ??= _interop.ImportSemaphore(_semaphorePair.Export(true));
}
_importedImage ??= _interop.ImportImage(_image.Export(),
@@ -143,7 +138,7 @@ class VulkanSwapchainImage : ISwapchainImage
MemorySize = _image.MemorySize
});
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ if (_image.IsDirectXBacked)
_lastPresent = _target.UpdateWithKeyedMutexAsync(_importedImage, 1, 0);
else
_lastPresent = _target.UpdateWithSemaphoresAsync(_importedImage, _renderCompletedSemaphore!, _availableSemaphore!);
diff --git a/src/Avalonia.Base/Avalonia.Base.csproj b/src/Avalonia.Base/Avalonia.Base.csproj
index 3c80f1866c..8d691c3586 100644
--- a/src/Avalonia.Base/Avalonia.Base.csproj
+++ b/src/Avalonia.Base/Avalonia.Base.csproj
@@ -34,6 +34,7 @@
+
diff --git a/src/Avalonia.Base/Platform/Interop/Utf8Buffer.cs b/src/Avalonia.Base/Platform/Interop/Utf8Buffer.cs
index ce9b38ead2..ac9398c99b 100644
--- a/src/Avalonia.Base/Platform/Interop/Utf8Buffer.cs
+++ b/src/Avalonia.Base/Platform/Interop/Utf8Buffer.cs
@@ -56,5 +56,8 @@ namespace Avalonia.Platform.Interop
ArrayPool.Shared.Return(bytes);
}
}
+
+ public static implicit operator IntPtr(Utf8Buffer b) => b.handle;
+ public static unsafe implicit operator byte*(Utf8Buffer b) => (byte*)b.handle;
}
}
diff --git a/src/Avalonia.Base/Platform/PlatformGraphicsExternalMemory.cs b/src/Avalonia.Base/Platform/PlatformGraphicsExternalMemory.cs
index 4b47c93eb5..b9be1f7dc9 100644
--- a/src/Avalonia.Base/Platform/PlatformGraphicsExternalMemory.cs
+++ b/src/Avalonia.Base/Platform/PlatformGraphicsExternalMemory.cs
@@ -35,6 +35,14 @@ public static class KnownPlatformGraphicsExternalImageHandleTypes
/// A POSIX file descriptor that's exported by Vulkan using VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT or in a compatible way
///
public const string VulkanOpaquePosixFileDescriptor = nameof(VulkanOpaquePosixFileDescriptor);
+
+ ///
+ /// A NT handle that's been exported by Vulkan using VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT or in a compatible way
+ ///
+ public const string VulkanOpaqueNtHandle = nameof(VulkanOpaqueNtHandle);
+
+ // A global shared handle that's been exported by Vulkan using VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT or in a compatible way
+ public const string VulkanOpaqueKmtHandle = nameof(VulkanOpaqueKmtHandle);
}
///
diff --git a/src/Avalonia.Vulkan/Avalonia.Vulkan.csproj b/src/Avalonia.Vulkan/Avalonia.Vulkan.csproj
new file mode 100644
index 0000000000..7ade700b64
--- /dev/null
+++ b/src/Avalonia.Vulkan/Avalonia.Vulkan.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net6.0;netstandard2.0
+ true
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Vulkan/IVulkanContextExternalObjectsFeature.cs b/src/Avalonia.Vulkan/IVulkanContextExternalObjectsFeature.cs
new file mode 100644
index 0000000000..9d64f3f687
--- /dev/null
+++ b/src/Avalonia.Vulkan/IVulkanContextExternalObjectsFeature.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Metadata;
+using Avalonia.Platform;
+using Avalonia.Rendering.Composition;
+
+namespace Avalonia.Vulkan;
+
+[Unstable]
+public interface IVulkanContextExternalObjectsFeature
+{
+ IReadOnlyList SupportedImageHandleTypes { get; }
+ IReadOnlyList SupportedSemaphoreTypes { get; }
+ byte[]? DeviceUuid { get; }
+ byte[]? DeviceLuid { get; }
+ CompositionGpuImportedImageSynchronizationCapabilities GetSynchronizationCapabilities(string imageHandleType);
+ IVulkanExternalImage ImportImage(IPlatformHandle handle, PlatformGraphicsExternalImageProperties properties);
+ IVulkanExternalSemaphore ImportSemaphore(IPlatformHandle handle);
+}
+
+[Unstable]
+public interface IVulkanExternalSemaphore : IDisposable
+{
+ ulong Handle { get; }
+ void SubmitWaitSemaphore();
+ void SubmitSignalSemaphore();
+}
+
+[Unstable]
+public interface IVulkanExternalImage : IDisposable
+{
+ VulkanImageInfo Info { get; }
+}
diff --git a/src/Avalonia.Vulkan/IVulkanDevice.cs b/src/Avalonia.Vulkan/IVulkanDevice.cs
new file mode 100644
index 0000000000..66dafac990
--- /dev/null
+++ b/src/Avalonia.Vulkan/IVulkanDevice.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Metadata;
+using Avalonia.Platform;
+using Avalonia.Vulkan.UnmanagedInterop;
+
+namespace Avalonia.Vulkan;
+public interface IVulkanDevice : IDisposable, IOptionalFeatureProvider
+{
+ public IntPtr Handle { get; }
+ public IntPtr PhysicalDeviceHandle { get; }
+ public IntPtr MainQueueHandle { get; }
+ public uint GraphicsQueueFamilyIndex { get; }
+ public IVulkanInstance Instance { get; }
+ bool IsLost { get; }
+ public IDisposable Lock();
+ public IEnumerable EnabledExtensions { get; }
+}
+
+public interface IVulkanInstance
+{
+ public IntPtr Handle { get; }
+ public IntPtr GetInstanceProcAddress(IntPtr instance, string name);
+ public IntPtr GetDeviceProcAddress(IntPtr device, string name);
+ public IEnumerable EnabledExtensions { get; }
+}
+
+[NotClientImplementable]
+public interface IVulkanPlatformGraphicsContext : IPlatformGraphicsContext
+{
+ IVulkanDevice Device { get; }
+ IVulkanInstance Instance { get; }
+ internal VulkanInstanceApi InstanceApi { get; }
+ internal VulkanDeviceApi DeviceApi { get; }
+ internal VkDevice DeviceHandle { get; }
+ internal VkPhysicalDevice PhysicalDeviceHandle { get; }
+ internal VkInstance InstanceHandle { get; }
+ internal VkQueue MainQueueHandle { get; }
+ internal uint GraphicsQueueFamilyIndex { get; }
+ IVulkanRenderTarget CreateRenderTarget(IEnumerable