diff --git a/Avalonia.sln b/Avalonia.sln
index e6898131b0..04feef5683 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -232,6 +232,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Browser.Blaz
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveUIDemo", "samples\ReactiveUIDemo\ReactiveUIDemo.csproj", "{75C47156-C5D8-44BC-A5A7-E8657C2248D6}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Vulkan", "src\Avalonia.Vulkan\Avalonia.Vulkan.csproj", "{3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -543,6 +545,10 @@ Global
{75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{75C47156-C5D8-44BC-A5A7-E8657C2248D6}.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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/build/CoreLibraries.props b/build/CoreLibraries.props
index 00a1e3094b..0432141f0b 100644
--- a/build/CoreLibraries.props
+++ b/build/CoreLibraries.props
@@ -4,6 +4,7 @@
+
diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs
index d5e5cb14dc..1496cb82dd 100644
--- a/samples/ControlCatalog.NetCore/Program.cs
+++ b/samples/ControlCatalog.NetCore/Program.cs
@@ -10,7 +10,7 @@ using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Headless;
using Avalonia.LogicalTree;
using Avalonia.Threading;
-
+using Avalonia.Vulkan;
using ControlCatalog.Pages;
namespace ControlCatalog.NetCore
@@ -122,7 +122,15 @@ namespace ControlCatalog.NetCore
{
EnableMultiTouch = true,
UseDBusMenu = true,
- EnableIme = true
+ EnableIme = true,
+ UseVulkan = true
+ })
+ .With(new VulkanOptions
+ {
+ VulkanInstanceCreationOptions = new ()
+ {
+ UseDebug = true
+ }
})
.UseSkia()
.AfterSetup(builder =>
diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
index 33501ece06..eca20b84e3 100644
--- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
+++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
@@ -7,10 +7,11 @@ using Android.Util;
using Android.Views;
using Avalonia.Android.Platform.SkiaPlatform;
using Avalonia.Platform;
+using Avalonia.Platform.Surfaces;
namespace Avalonia.Android
{
- public abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, IPlatformNativeSurfaceHandle
+ public abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, INativeHandlePlatformSurface
{
bool _invalidateQueued;
readonly object _lock = new object();
diff --git a/src/Avalonia.Base/Platform/Interop/Utf8Buffer.cs b/src/Avalonia.Base/Platform/Interop/Utf8Buffer.cs
index 7a0b5b34cd..22b0dff967 100644
--- a/src/Avalonia.Base/Platform/Interop/Utf8Buffer.cs
+++ b/src/Avalonia.Base/Platform/Interop/Utf8Buffer.cs
@@ -54,5 +54,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.Controls/Platform/IPlatformNativeSurfaceHandle.cs b/src/Avalonia.Controls/Platform/Surfaces/IPlatformNativeSurfaceHandle.cs
similarity index 58%
rename from src/Avalonia.Controls/Platform/IPlatformNativeSurfaceHandle.cs
rename to src/Avalonia.Controls/Platform/Surfaces/IPlatformNativeSurfaceHandle.cs
index 6ad07b1b13..5220792adc 100644
--- a/src/Avalonia.Controls/Platform/IPlatformNativeSurfaceHandle.cs
+++ b/src/Avalonia.Controls/Platform/Surfaces/IPlatformNativeSurfaceHandle.cs
@@ -1,10 +1,10 @@
using System;
using Avalonia.Metadata;
-namespace Avalonia.Platform
+namespace Avalonia.Platform.Surfaces
{
[Unstable]
- public interface IPlatformNativeSurfaceHandle : IPlatformHandle
+ public interface INativeHandlePlatformSurface : IPlatformHandle
{
PixelSize Size { get; }
double Scaling { get; }
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/IVulkanDevice.cs b/src/Avalonia.Vulkan/IVulkanDevice.cs
new file mode 100644
index 0000000000..45815adffc
--- /dev/null
+++ b/src/Avalonia.Vulkan/IVulkanDevice.cs
@@ -0,0 +1,34 @@
+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();
+}
+
+[NotClientImplementable]
+public interface IVulkanPlatformGraphicsContext : IPlatformGraphicsContext
+{
+ IVulkanDevice Device { get; }
+ IVulkanInstance Instance { get; }
+ internal VulkanInstanceApi InstanceApi { get; }
+ internal VulkanDeviceApi DeviceApi { get; }
+ IVulkanRenderTarget CreateRenderTarget(IEnumerable