diff --git a/include/Nazara/VulkanRenderer/Wrapper/Instance.hpp b/include/Nazara/VulkanRenderer/Wrapper/Instance.hpp index b63252bcd..13c31180e 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/Instance.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper/Instance.hpp @@ -34,6 +34,10 @@ #include #endif +#ifdef VK_USE_PLATFORM_METAL_EXT +#include +#endif + #ifdef VK_USE_PLATFORM_XLIB_KHR typedef struct _XDisplay Display; typedef unsigned long XID; diff --git a/include/Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp b/include/Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp index b59818039..42805549e 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp @@ -97,6 +97,12 @@ NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(VK_KHR_win32_surface) NAZARA_VULKANRENDERER_INSTANCE_EXT_END() #endif +#ifdef VK_USE_PLATFORM_METAL_EXT +NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(VK_EXT_metal_surface) + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateMetalSurfaceEXT) +NAZARA_VULKANRENDERER_INSTANCE_EXT_END() +#endif + #undef NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION #undef NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN #undef NAZARA_VULKANRENDERER_INSTANCE_EXT_END diff --git a/include/Nazara/VulkanRenderer/Wrapper/Surface.hpp b/include/Nazara/VulkanRenderer/Wrapper/Surface.hpp index 7ea5831b5..95157b889 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/Surface.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper/Surface.hpp @@ -12,6 +12,11 @@ #include #include +#ifdef VK_USE_PLATFORM_METAL_EXT +#include +#include +#endif + namespace Nz { namespace Vk @@ -54,6 +59,11 @@ namespace Nz inline bool Create(HINSTANCE instance, HWND handle, VkWin32SurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr); #endif + #ifdef VK_USE_PLATFORM_METAL_EXT + inline bool Create(const VkMetalSurfaceCreateInfoEXT& createInfo, const VkAllocationCallbacks* allocator = nullptr); + inline bool Create(id layer, const VkAllocationCallbacks* allocator = nullptr); + #endif + inline void Destroy(); bool GetCapabilities(VkPhysicalDevice physicalDevice, VkSurfaceCapabilitiesKHR* surfaceCapabilities) const; diff --git a/include/Nazara/VulkanRenderer/Wrapper/Surface.inl b/include/Nazara/VulkanRenderer/Wrapper/Surface.inl index a9beb4bca..5e6d6b4e8 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/Surface.inl +++ b/include/Nazara/VulkanRenderer/Wrapper/Surface.inl @@ -140,6 +140,27 @@ namespace Nz } #endif + #ifdef VK_USE_PLATFORM_METAL_EXT + inline bool Surface::Create(const VkMetalSurfaceCreateInfoEXT& createInfo, const VkAllocationCallbacks* allocator) + { + m_lastErrorCode = m_instance.vkCreateMetalSurfaceEXT(m_instance, &createInfo, allocator, &m_surface); + return Create(allocator); + } + + inline bool Surface::Create(id layer, const VkAllocationCallbacks* allocator) + { + VkMetalSurfaceCreateInfoEXT createInfo = + { + VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT, + nullptr, + 0, + layer + }; + + return Create(createInfo, allocator); + } + #endif + inline void Surface::Destroy() { if (m_surface != VK_NULL_HANDLE) @@ -262,6 +283,10 @@ namespace Nz return true; #endif +#ifdef VK_USE_PLATFORM_METAL_EXT + if (instance.IsExtensionLoaded(VK_EXT_METAL_SURFACE_EXTENSION_NAME)) + return true; +#endif return false; } diff --git a/src/Nazara/VulkanRenderer/Vulkan.cpp b/src/Nazara/VulkanRenderer/Vulkan.cpp index 48407f42b..661d17e30 100644 --- a/src/Nazara/VulkanRenderer/Vulkan.cpp +++ b/src/Nazara/VulkanRenderer/Vulkan.cpp @@ -244,6 +244,10 @@ namespace Nz enabledExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); #endif + #ifdef VK_USE_PLATFORM_METAL_EXT + enabledExtensions.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME); + #endif + if (availableExtensions.count(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) enabledExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); diff --git a/src/Nazara/VulkanRenderer/VulkanSurface.cpp b/src/Nazara/VulkanRenderer/VulkanSurface.cpp index 80b186e56..3663e3c17 100644 --- a/src/Nazara/VulkanRenderer/VulkanSurface.cpp +++ b/src/Nazara/VulkanRenderer/VulkanSurface.cpp @@ -7,8 +7,17 @@ #include #include +#ifdef VK_USE_PLATFORM_METAL_EXT +#include +#include +#endif + namespace Nz { + #ifdef VK_USE_PLATFORM_METAL_EXT + id CreateAndAttachMetalLayer(void* window); + #endif + VulkanSurface::VulkanSurface() : m_surface(Vulkan::GetInstance()) { @@ -60,6 +69,11 @@ namespace Nz } } #elif defined(NAZARA_PLATFORM_MACOS) + { + NazaraAssert(handle.type == WindowBackend::Cocoa, "expected cocoa window"); + id layer = CreateAndAttachMetalLayer(handle.cocoa.window); + success = m_surface.Create(layer); + } #else #error This OS is not supported by Vulkan #endif diff --git a/src/Nazara/VulkanRenderer/VulkanSurfaceMetal.mm b/src/Nazara/VulkanRenderer/VulkanSurfaceMetal.mm new file mode 100644 index 000000000..3ea392a61 --- /dev/null +++ b/src/Nazara/VulkanRenderer/VulkanSurfaceMetal.mm @@ -0,0 +1,16 @@ +#import +#import +#import + +namespace Nz +{ + id CreateAndAttachMetalLayer(void* window) { + NSWindow* obj = (__bridge NSWindow*)window; + NSView* view = [[NSView alloc] initWithFrame:obj.frame]; + [view setLayer:[CAMetalLayer layer]]; + [view setWantsLayer:YES]; + view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; + [obj.contentView addSubview:view]; + return view.layer; + } +} diff --git a/xmake.lua b/xmake.lua index d50f51962..1567a9b7b 100644 --- a/xmake.lua +++ b/xmake.lua @@ -103,6 +103,8 @@ local modules = { add_defines("VK_USE_PLATFORM_WAYLAND_KHR") elseif is_plat("macosx") then add_defines("VK_USE_PLATFORM_METAL_EXT") + add_files("src/Nazara/VulkanRenderer/**.mm") + add_frameworks("quartzcore", "AppKit") end end },