VulkanRenderer: implement metal view
The metal view backing the MoltenVK compatibility wrapper is written in Obj-C. It would have been possible to use the Objective-C runtime in C++ but the code is less performant (the symbol binding is done at first use instead of the beginning of the program) and actually harder to get right. Note that MoltenVK is not linked to the loader, so the libMoltenVK.dylib object must be available for loading.
This commit is contained in:
parent
162456c5b6
commit
f146661a76
|
|
@ -34,6 +34,10 @@
|
||||||
#include <vulkan/vulkan_xcb.h>
|
#include <vulkan/vulkan_xcb.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef VK_USE_PLATFORM_METAL_EXT
|
||||||
|
#include <vulkan/vulkan_metal.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
||||||
typedef struct _XDisplay Display;
|
typedef struct _XDisplay Display;
|
||||||
typedef unsigned long XID;
|
typedef unsigned long XID;
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,12 @@ NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(VK_KHR_win32_surface)
|
||||||
NAZARA_VULKANRENDERER_INSTANCE_EXT_END()
|
NAZARA_VULKANRENDERER_INSTANCE_EXT_END()
|
||||||
#endif
|
#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_CORE_EXT_FUNCTION
|
||||||
#undef NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN
|
#undef NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN
|
||||||
#undef NAZARA_VULKANRENDERER_INSTANCE_EXT_END
|
#undef NAZARA_VULKANRENDERER_INSTANCE_EXT_END
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,11 @@
|
||||||
#include <Nazara/VulkanRenderer/Wrapper/Instance.hpp>
|
#include <Nazara/VulkanRenderer/Wrapper/Instance.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Wrapper/Loader.hpp>
|
#include <Nazara/VulkanRenderer/Wrapper/Loader.hpp>
|
||||||
|
|
||||||
|
#ifdef VK_USE_PLATFORM_METAL_EXT
|
||||||
|
#include <objc/runtime.h>
|
||||||
|
#include <vulkan/vulkan_metal.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
namespace Vk
|
namespace Vk
|
||||||
|
|
@ -54,6 +59,11 @@ namespace Nz
|
||||||
inline bool Create(HINSTANCE instance, HWND handle, VkWin32SurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr);
|
inline bool Create(HINSTANCE instance, HWND handle, VkWin32SurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr);
|
||||||
#endif
|
#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();
|
inline void Destroy();
|
||||||
|
|
||||||
bool GetCapabilities(VkPhysicalDevice physicalDevice, VkSurfaceCapabilitiesKHR* surfaceCapabilities) const;
|
bool GetCapabilities(VkPhysicalDevice physicalDevice, VkSurfaceCapabilitiesKHR* surfaceCapabilities) const;
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,27 @@ namespace Nz
|
||||||
}
|
}
|
||||||
#endif
|
#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()
|
inline void Surface::Destroy()
|
||||||
{
|
{
|
||||||
if (m_surface != VK_NULL_HANDLE)
|
if (m_surface != VK_NULL_HANDLE)
|
||||||
|
|
@ -262,6 +283,10 @@ namespace Nz
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef VK_USE_PLATFORM_METAL_EXT
|
||||||
|
if (instance.IsExtensionLoaded(VK_EXT_METAL_SURFACE_EXTENSION_NAME))
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -244,6 +244,10 @@ namespace Nz
|
||||||
enabledExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
enabledExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||||
#endif
|
#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))
|
if (availableExtensions.count(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
|
||||||
enabledExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
enabledExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,17 @@
|
||||||
#include <vulkan/vk_sdk_platform.h>
|
#include <vulkan/vk_sdk_platform.h>
|
||||||
#include <Nazara/VulkanRenderer/Debug.hpp>
|
#include <Nazara/VulkanRenderer/Debug.hpp>
|
||||||
|
|
||||||
|
#ifdef VK_USE_PLATFORM_METAL_EXT
|
||||||
|
#include <objc/runtime.h>
|
||||||
|
#include <vulkan/vulkan_metal.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
#ifdef VK_USE_PLATFORM_METAL_EXT
|
||||||
|
id CreateAndAttachMetalLayer(void* window);
|
||||||
|
#endif
|
||||||
|
|
||||||
VulkanSurface::VulkanSurface() :
|
VulkanSurface::VulkanSurface() :
|
||||||
m_surface(Vulkan::GetInstance())
|
m_surface(Vulkan::GetInstance())
|
||||||
{
|
{
|
||||||
|
|
@ -60,6 +69,11 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#elif defined(NAZARA_PLATFORM_MACOS)
|
#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
|
#else
|
||||||
#error This OS is not supported by Vulkan
|
#error This OS is not supported by Vulkan
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#import <AppKit/NSView.h>
|
||||||
|
#import <AppKit/NSWindow.h>
|
||||||
|
#import <QuartzCore/CAMetalLayer.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -103,6 +103,8 @@ local modules = {
|
||||||
add_defines("VK_USE_PLATFORM_WAYLAND_KHR")
|
add_defines("VK_USE_PLATFORM_WAYLAND_KHR")
|
||||||
elseif is_plat("macosx") then
|
elseif is_plat("macosx") then
|
||||||
add_defines("VK_USE_PLATFORM_METAL_EXT")
|
add_defines("VK_USE_PLATFORM_METAL_EXT")
|
||||||
|
add_files("src/Nazara/VulkanRenderer/**.mm")
|
||||||
|
add_frameworks("quartzcore", "AppKit")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue