From b581cc4777925e17423f7bcdec9dcb02bf9d1423 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sun, 7 Aug 2022 01:28:43 +1000 Subject: [PATCH] Vulkan/SwapChain: Fix crash on fullscreen with MoltenVK --- src/common/vulkan/swap_chain.cpp | 34 ++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/common/vulkan/swap_chain.cpp b/src/common/vulkan/swap_chain.cpp index 5a2163e83..d9cb6620d 100644 --- a/src/common/vulkan/swap_chain.cpp +++ b/src/common/vulkan/swap_chain.cpp @@ -18,10 +18,35 @@ Log_SetChannel(Vulkan::SwapChain); #endif #if defined(__APPLE__) +#include #include +static bool IsMainThread() +{ + Class clsNSThread = objc_getClass("NSThread"); + if (!clsNSThread) + return false; + + return reinterpret_cast(objc_msgSend)(clsNSThread, sel_getUid("isMainThread")); +} + static bool CreateMetalLayer(WindowInfo* wi) { + if (!IsMainThread()) + { + struct MainThreadParams + { + WindowInfo* wi; + bool result; + }; + MainThreadParams params = {wi, false}; + dispatch_sync_f(dispatch_get_main_queue(), ¶ms, [](void* vparams) { + MainThreadParams* params = static_cast(vparams); + params->result = CreateMetalLayer(params->wi); + }); + return params.result; + } + id view = reinterpret_cast(wi->window_handle); Class clsCAMetalLayer = objc_getClass("CAMetalLayer"); @@ -32,7 +57,7 @@ static bool CreateMetalLayer(WindowInfo* wi) } // [CAMetalLayer layer] - id layer = reinterpret_cast(objc_msgSend)(objc_getClass("CAMetalLayer"), sel_getUid("layer")); + id layer = reinterpret_cast(objc_msgSend)(clsCAMetalLayer, sel_getUid("layer")); if (!layer) { Log_ErrorPrint("Failed to create Metal layer."); @@ -61,6 +86,12 @@ static bool CreateMetalLayer(WindowInfo* wi) static void DestroyMetalLayer(WindowInfo* wi) { + if (!IsMainThread()) + { + dispatch_sync_f(dispatch_get_main_queue(), wi, [](void* wi) { DestroyMetalLayer(static_cast(wi)); }); + return; + } + id view = reinterpret_cast(wi->window_handle); id layer = reinterpret_cast(wi->surface_handle); if (layer == nil) @@ -68,7 +99,6 @@ static void DestroyMetalLayer(WindowInfo* wi) reinterpret_cast(objc_msgSend)(view, sel_getUid("setLayer:"), nil); reinterpret_cast(objc_msgSend)(view, sel_getUid("setWantsLayer:"), NO); - reinterpret_cast(objc_msgSend)(layer, sel_getUid("release")); wi->surface_handle = nullptr; }