Vulkan: Switch from vkCreateMacOSSurfaceMVK() to vkCreateMetalSurfaceEXT()

Since we are calling this off the UI thread, we can't use anything which
accesses the underlying NSView object. We create and set the Metal layer
on the UI thread before the video backend is initialized. This extension
is both compatible with MoltenVK and gfx-portability for accepting a
layer at surface creation.
This commit is contained in:
Stenzek 2020-04-07 18:49:40 +10:00
parent 52d4756679
commit a2f4fafe86
5 changed files with 14 additions and 13 deletions

View File

@ -107,17 +107,18 @@ VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, const WindowSys
}
#endif
#if defined(VK_USE_PLATFORM_MACOS_MVK)
#if defined(VK_USE_PLATFORM_METAL_EXT)
if (wsi.type == WindowSystemType::MacOS)
{
VkMacOSSurfaceCreateInfoMVK surface_create_info = {
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK, nullptr, 0, wsi.render_surface};
VkMetalSurfaceCreateInfoEXT surface_create_info = {
VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT, nullptr, 0,
static_cast<const CAMetalLayer*>(wsi.render_surface)};
VkSurfaceKHR surface;
VkResult res = vkCreateMacOSSurfaceMVK(instance, &surface_create_info, nullptr, &surface);
VkResult res = vkCreateMetalSurfaceEXT(instance, &surface_create_info, nullptr, &surface);
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkCreateMacOSSurfaceMVK failed: ");
LOG_VULKAN_ERROR(res, "vkCreateMetalSurfaceEXT failed: ");
return VK_NULL_HANDLE;
}

View File

@ -211,8 +211,8 @@ bool VulkanContext::SelectInstanceExtensions(std::vector<const char*>* extension
return false;
}
#endif
#if defined(VK_USE_PLATFORM_MACOS_MVK)
if (wstype == WindowSystemType::MacOS && !AddExtension(VK_MVK_MACOS_SURFACE_EXTENSION_NAME, true))
#if defined(VK_USE_PLATFORM_METAL_EXT)
if (wstype == WindowSystemType::MacOS && !AddExtension(VK_EXT_METAL_SURFACE_EXTENSION_NAME, true))
{
return false;
}

View File

@ -53,8 +53,8 @@ VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceXlibPresentationSupportKHR, false
VULKAN_INSTANCE_ENTRY_POINT(vkCreateAndroidSurfaceKHR, false)
#endif
#if defined(VK_USE_PLATFORM_MACOS_MVK)
VULKAN_INSTANCE_ENTRY_POINT(vkCreateMacOSSurfaceMVK, false)
#if defined(VK_USE_PLATFORM_METAL_EXT)
VULKAN_INSTANCE_ENTRY_POINT(vkCreateMetalSurfaceEXT, false)
#endif
VULKAN_INSTANCE_ENTRY_POINT(vkCreateDebugReportCallbackEXT, false)

View File

@ -19,7 +19,7 @@
#endif
#if defined(__APPLE__)
#define VK_USE_PLATFORM_MACOS_MVK
#define VK_USE_PLATFORM_METAL_EXT
#endif
#include "vulkan/vulkan.h"

View File

@ -23,7 +23,7 @@
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h"
#if defined(VK_USE_PLATFORM_MACOS_MVK)
#if defined(VK_USE_PLATFORM_METAL_EXT)
#include <objc/message.h>
#endif
@ -280,7 +280,7 @@ void VideoBackend::Shutdown()
UnloadVulkanLibrary();
}
#if defined(VK_USE_PLATFORM_MACOS_MVK)
#if defined(VK_USE_PLATFORM_METAL_EXT)
static bool IsRunningOnMojaveOrHigher()
{
// id processInfo = [NSProcessInfo processInfo]
@ -306,7 +306,7 @@ static bool IsRunningOnMojaveOrHigher()
void VideoBackend::PrepareWindow(WindowSystemInfo& wsi)
{
#if defined(VK_USE_PLATFORM_MACOS_MVK)
#if defined(VK_USE_PLATFORM_METAL_EXT)
// This is kinda messy, but it avoids having to write Objective C++ just to create a metal layer.
id view = reinterpret_cast<id>(wsi.render_surface);
Class clsCAMetalLayer = objc_getClass("CAMetalLayer");