From 9552103c5886391fd6c02920f201b8bf480dc7eb Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sun, 20 Apr 2025 16:00:21 +0300 Subject: [PATCH] Add support for `VK_EXT_metal_surface` extension --- .../Vulkan/Android/AndroidVulkanPlatform.cpp | 2 +- .../Vulkan/Android/AndroidVulkanPlatform.h | 4 +++- .../Vulkan/GPUSwapChainVulkan.cpp | 2 +- .../Vulkan/Linux/LinuxVulkanPlatform.cpp | 2 +- .../Vulkan/Linux/LinuxVulkanPlatform.h | 4 +++- .../Vulkan/Mac/MacVulkanPlatform.cpp | 24 ++++++++++++++----- .../Vulkan/Mac/MacVulkanPlatform.h | 4 +++- .../Vulkan/Win32/Win32VulkanPlatform.cpp | 2 +- .../Vulkan/Win32/Win32VulkanPlatform.h | 4 +++- .../Vulkan/iOS/iOSVulkanPlatform.cpp | 2 +- .../Vulkan/iOS/iOSVulkanPlatform.h | 4 +++- Source/ThirdParty/volk/volk.Build.cs | 1 + 12 files changed, 39 insertions(+), 16 deletions(-) diff --git a/Source/Engine/GraphicsDevice/Vulkan/Android/AndroidVulkanPlatform.cpp b/Source/Engine/GraphicsDevice/Vulkan/Android/AndroidVulkanPlatform.cpp index 93d758d3a..3d4183be0 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/Android/AndroidVulkanPlatform.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/Android/AndroidVulkanPlatform.cpp @@ -18,7 +18,7 @@ void AndroidVulkanPlatform::GetDeviceExtensions(Array& extensions, extensions.Add(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); } -void AndroidVulkanPlatform::CreateSurface(Window* window, VkInstance instance, VkSurfaceKHR* surface) +void AndroidVulkanPlatform::CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* surface) { ASSERT(window); void* windowHandle = window->GetNativePtr(); diff --git a/Source/Engine/GraphicsDevice/Vulkan/Android/AndroidVulkanPlatform.h b/Source/Engine/GraphicsDevice/Vulkan/Android/AndroidVulkanPlatform.h index e8c7f77aa..9a7dbe5b8 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/Android/AndroidVulkanPlatform.h +++ b/Source/Engine/GraphicsDevice/Vulkan/Android/AndroidVulkanPlatform.h @@ -9,6 +9,8 @@ // Support more backbuffers in case driver decides to use more #define VULKAN_BACK_BUFFERS_COUNT_MAX 8 +class GPUDeviceVulkan; + /// /// The implementation for the Vulkan API support for Android platform. /// @@ -17,7 +19,7 @@ class AndroidVulkanPlatform : public VulkanPlatformBase public: static void GetInstanceExtensions(Array& extensions, Array& layers); static void GetDeviceExtensions(Array& extensions, Array& layers); - static void CreateSurface(Window* window, VkInstance instance, VkSurfaceKHR* surface); + static void CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* surface); }; typedef AndroidVulkanPlatform VulkanPlatform; diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp index 01c0fce79..5aa79ed75 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp @@ -192,7 +192,7 @@ bool GPUSwapChainVulkan::CreateSwapChain(int32 width, int32 height) ASSERT_LOW_LAYER(_backBuffers.Count() == 0); // Create platform-dependent surface - VulkanPlatform::CreateSurface(_window, GPUDeviceVulkan::Instance, &_surface); + VulkanPlatform::CreateSurface(_window, _device, GPUDeviceVulkan::Instance, &_surface); if (_surface == VK_NULL_HANDLE) { LOG(Warning, "Failed to create Vulkan surface."); diff --git a/Source/Engine/GraphicsDevice/Vulkan/Linux/LinuxVulkanPlatform.cpp b/Source/Engine/GraphicsDevice/Vulkan/Linux/LinuxVulkanPlatform.cpp index cb5403786..272f8e226 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/Linux/LinuxVulkanPlatform.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/Linux/LinuxVulkanPlatform.cpp @@ -30,7 +30,7 @@ void LinuxVulkanPlatform::GetInstanceExtensions(Array& extensions, extensions.Add(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); } -void LinuxVulkanPlatform::CreateSurface(Window* window, VkInstance instance, VkSurfaceKHR* surface) +void LinuxVulkanPlatform::CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* surface) { #if !PLATFORM_SDL void* windowHandle = window->GetNativePtr(); diff --git a/Source/Engine/GraphicsDevice/Vulkan/Linux/LinuxVulkanPlatform.h b/Source/Engine/GraphicsDevice/Vulkan/Linux/LinuxVulkanPlatform.h index 544bbd499..11d2008cd 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/Linux/LinuxVulkanPlatform.h +++ b/Source/Engine/GraphicsDevice/Vulkan/Linux/LinuxVulkanPlatform.h @@ -12,6 +12,8 @@ // Prevent wierd error 'Invalid VkValidationCacheEXT Object' #define VULKAN_USE_VALIDATION_CACHE 0 +class GPUDeviceVulkan; + /// /// The implementation for the Vulkan API support for Linux platform. /// @@ -19,7 +21,7 @@ class LinuxVulkanPlatform : public VulkanPlatformBase { public: static void GetInstanceExtensions(Array& extensions, Array& layers); - static void CreateSurface(Window* window, VkInstance instance, VkSurfaceKHR* outSurface); + static void CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* outSurface); }; typedef LinuxVulkanPlatform VulkanPlatform; diff --git a/Source/Engine/GraphicsDevice/Vulkan/Mac/MacVulkanPlatform.cpp b/Source/Engine/GraphicsDevice/Vulkan/Mac/MacVulkanPlatform.cpp index 771011bea..a2cfc07e4 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/Mac/MacVulkanPlatform.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/Mac/MacVulkanPlatform.cpp @@ -5,16 +5,18 @@ #include "MacVulkanPlatform.h" #include "../RenderToolsVulkan.h" #include "Engine/Platform/Window.h" +#include "Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h" #include #include void MacVulkanPlatform::GetInstanceExtensions(Array& extensions, Array& layers) { extensions.Add(VK_KHR_SURFACE_EXTENSION_NAME); - extensions.Add(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); + extensions.Add(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); + extensions.Add(VK_EXT_METAL_SURFACE_EXTENSION_NAME); } -void MacVulkanPlatform::CreateSurface(Window* window, VkInstance instance, VkSurfaceKHR* surface) +void MacVulkanPlatform::CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* surface) { void* windowHandle = window->GetNativePtr(); NSWindow* nswindow = (NSWindow*)windowHandle; @@ -22,10 +24,20 @@ void MacVulkanPlatform::CreateSurface(Window* window, VkInstance instance, VkSur nswindow.contentView.wantsLayer = YES; nswindow.contentView.layer = [CAMetalLayer layer]; #endif - VkMacOSSurfaceCreateInfoMVK surfaceCreateInfo; - RenderToolsVulkan::ZeroStruct(surfaceCreateInfo, VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK); - surfaceCreateInfo.pView = (void*)nswindow.contentView; - VALIDATE_VULKAN_RESULT(vkCreateMacOSSurfaceMVK(instance, &surfaceCreateInfo, nullptr, surface)); + if (device->InstanceExtensions.Contains(VK_EXT_METAL_SURFACE_EXTENSION_NAME)) + { + VkMetalSurfaceCreateInfoEXT surfaceCreateInfo; + RenderToolsVulkan::ZeroStruct(surfaceCreateInfo, VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT); + surfaceCreateInfo.pLayer = (CAMetalLayer*)nswindow.contentView.layer; + VALIDATE_VULKAN_RESULT(vkCreateMetalSurfaceEXT(instance, &surfaceCreateInfo, nullptr, surface)); + } + else + { + VkMacOSSurfaceCreateInfoMVK surfaceCreateInfo; + RenderToolsVulkan::ZeroStruct(surfaceCreateInfo, VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK); + surfaceCreateInfo.pView = (void*)nswindow.contentView; + VALIDATE_VULKAN_RESULT(vkCreateMacOSSurfaceMVK(instance, &surfaceCreateInfo, nullptr, surface)); + } } #endif diff --git a/Source/Engine/GraphicsDevice/Vulkan/Mac/MacVulkanPlatform.h b/Source/Engine/GraphicsDevice/Vulkan/Mac/MacVulkanPlatform.h index b4d32fdc8..5643a04c0 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/Mac/MacVulkanPlatform.h +++ b/Source/Engine/GraphicsDevice/Vulkan/Mac/MacVulkanPlatform.h @@ -11,6 +11,8 @@ // General/Validation Error:0 VK_ERROR_INITIALIZATION_FAILED: Could not create MTLCounterSampleBuffer for query pool of type VK_QUERY_TYPE_TIMESTAMP. Reverting to emulated behavior. (Error code 0): Cannot allocate sample buffer #define VULKAN_USE_QUERIES 0 +class GPUDeviceVulkan; + /// /// The implementation for the Vulkan API support for Mac platform. /// @@ -18,7 +20,7 @@ class MacVulkanPlatform : public VulkanPlatformBase { public: static void GetInstanceExtensions(Array& extensions, Array& layers); - static void CreateSurface(Window* window, VkInstance instance, VkSurfaceKHR* outSurface); + static void CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* outSurface); }; typedef MacVulkanPlatform VulkanPlatform; diff --git a/Source/Engine/GraphicsDevice/Vulkan/Win32/Win32VulkanPlatform.cpp b/Source/Engine/GraphicsDevice/Vulkan/Win32/Win32VulkanPlatform.cpp index 6f02d4bbe..08bd300ae 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/Win32/Win32VulkanPlatform.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/Win32/Win32VulkanPlatform.cpp @@ -14,7 +14,7 @@ void Win32VulkanPlatform::GetInstanceExtensions(Array& extensions, extensions.Add(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); } -void Win32VulkanPlatform::CreateSurface(Window* window, VkInstance instance, VkSurfaceKHR* surface) +void Win32VulkanPlatform::CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* surface) { void* windowHandle = window->GetNativePtr(); VkWin32SurfaceCreateInfoKHR surfaceCreateInfo; diff --git a/Source/Engine/GraphicsDevice/Vulkan/Win32/Win32VulkanPlatform.h b/Source/Engine/GraphicsDevice/Vulkan/Win32/Win32VulkanPlatform.h index 99c6a6f8f..2de527e2f 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/Win32/Win32VulkanPlatform.h +++ b/Source/Engine/GraphicsDevice/Vulkan/Win32/Win32VulkanPlatform.h @@ -10,6 +10,8 @@ #define VULKAN_USE_PLATFORM_WIN32_KHX 1 #define VULKAN_USE_CREATE_WIN32_SURFACE 1 +class GPUDeviceVulkan; + /// /// The implementation for the Vulkan API support for Win32 platform. /// @@ -17,7 +19,7 @@ class Win32VulkanPlatform : public VulkanPlatformBase { public: static void GetInstanceExtensions(Array& extensions, Array& layers); - static void CreateSurface(Window* window, VkInstance instance, VkSurfaceKHR* surface); + static void CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* surface); }; typedef Win32VulkanPlatform VulkanPlatform; diff --git a/Source/Engine/GraphicsDevice/Vulkan/iOS/iOSVulkanPlatform.cpp b/Source/Engine/GraphicsDevice/Vulkan/iOS/iOSVulkanPlatform.cpp index c95811ded..58b4e3183 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/iOS/iOSVulkanPlatform.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/iOS/iOSVulkanPlatform.cpp @@ -14,7 +14,7 @@ void iOSVulkanPlatform::GetInstanceExtensions(Array& extensions, Ar extensions.Add(VK_MVK_IOS_SURFACE_EXTENSION_NAME); } -void iOSVulkanPlatform::CreateSurface(Window* window, VkInstance instance, VkSurfaceKHR* surface) +void iOSVulkanPlatform::CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* surface) { void* windowHandle = window->GetNativePtr(); // Create surface on a main UI Thread diff --git a/Source/Engine/GraphicsDevice/Vulkan/iOS/iOSVulkanPlatform.h b/Source/Engine/GraphicsDevice/Vulkan/iOS/iOSVulkanPlatform.h index a56e6eb1a..011ef9246 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/iOS/iOSVulkanPlatform.h +++ b/Source/Engine/GraphicsDevice/Vulkan/iOS/iOSVulkanPlatform.h @@ -11,6 +11,8 @@ // General/Validation Error:0 VK_ERROR_INITIALIZATION_FAILED: Could not create MTLCounterSampleBuffer for query pool of type VK_QUERY_TYPE_TIMESTAMP. Reverting to emulated behavior. (Error code 0): Cannot allocate sample buffer #define VULKAN_USE_QUERIES 0 +class GPUDeviceVulkan; + /// /// The implementation for the Vulkan API support for iOS platform. /// @@ -18,7 +20,7 @@ class iOSVulkanPlatform : public VulkanPlatformBase { public: static void GetInstanceExtensions(Array& extensions, Array& layers); - static void CreateSurface(Window* window, VkInstance instance, VkSurfaceKHR* outSurface); + static void CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* outSurface); }; typedef iOSVulkanPlatform VulkanPlatform; diff --git a/Source/ThirdParty/volk/volk.Build.cs b/Source/ThirdParty/volk/volk.Build.cs index a052a6d7c..3d46c52d9 100644 --- a/Source/ThirdParty/volk/volk.Build.cs +++ b/Source/ThirdParty/volk/volk.Build.cs @@ -43,6 +43,7 @@ public class volk : ThirdPartyModule break; case TargetPlatform.Mac: options.PublicDefinitions.Add("VK_USE_PLATFORM_MACOS_MVK"); + options.PublicDefinitions.Add("VK_USE_PLATFORM_METAL_EXT"); break; case TargetPlatform.iOS: options.PublicDefinitions.Add("VK_USE_PLATFORM_IOS_MVK");