Vulkan/SwapChain: Fix crash on fullscreen with MoltenVK
This commit is contained in:
parent
093979a65a
commit
b581cc4777
|
@ -18,10 +18,35 @@ Log_SetChannel(Vulkan::SwapChain);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
|
#include <dispatch/dispatch.h>
|
||||||
#include <objc/message.h>
|
#include <objc/message.h>
|
||||||
|
|
||||||
|
static bool IsMainThread()
|
||||||
|
{
|
||||||
|
Class clsNSThread = objc_getClass("NSThread");
|
||||||
|
if (!clsNSThread)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return reinterpret_cast<BOOL (*)(Class, SEL)>(objc_msgSend)(clsNSThread, sel_getUid("isMainThread"));
|
||||||
|
}
|
||||||
|
|
||||||
static bool CreateMetalLayer(WindowInfo* wi)
|
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<MainThreadParams*>(vparams);
|
||||||
|
params->result = CreateMetalLayer(params->wi);
|
||||||
|
});
|
||||||
|
return params.result;
|
||||||
|
}
|
||||||
|
|
||||||
id view = reinterpret_cast<id>(wi->window_handle);
|
id view = reinterpret_cast<id>(wi->window_handle);
|
||||||
|
|
||||||
Class clsCAMetalLayer = objc_getClass("CAMetalLayer");
|
Class clsCAMetalLayer = objc_getClass("CAMetalLayer");
|
||||||
|
@ -32,7 +57,7 @@ static bool CreateMetalLayer(WindowInfo* wi)
|
||||||
}
|
}
|
||||||
|
|
||||||
// [CAMetalLayer layer]
|
// [CAMetalLayer layer]
|
||||||
id layer = reinterpret_cast<id (*)(Class, SEL)>(objc_msgSend)(objc_getClass("CAMetalLayer"), sel_getUid("layer"));
|
id layer = reinterpret_cast<id (*)(Class, SEL)>(objc_msgSend)(clsCAMetalLayer, sel_getUid("layer"));
|
||||||
if (!layer)
|
if (!layer)
|
||||||
{
|
{
|
||||||
Log_ErrorPrint("Failed to create Metal layer.");
|
Log_ErrorPrint("Failed to create Metal layer.");
|
||||||
|
@ -61,6 +86,12 @@ static bool CreateMetalLayer(WindowInfo* wi)
|
||||||
|
|
||||||
static void DestroyMetalLayer(WindowInfo* wi)
|
static void DestroyMetalLayer(WindowInfo* wi)
|
||||||
{
|
{
|
||||||
|
if (!IsMainThread())
|
||||||
|
{
|
||||||
|
dispatch_sync_f(dispatch_get_main_queue(), wi, [](void* wi) { DestroyMetalLayer(static_cast<WindowInfo*>(wi)); });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
id view = reinterpret_cast<id>(wi->window_handle);
|
id view = reinterpret_cast<id>(wi->window_handle);
|
||||||
id layer = reinterpret_cast<id>(wi->surface_handle);
|
id layer = reinterpret_cast<id>(wi->surface_handle);
|
||||||
if (layer == nil)
|
if (layer == nil)
|
||||||
|
@ -68,7 +99,6 @@ static void DestroyMetalLayer(WindowInfo* wi)
|
||||||
|
|
||||||
reinterpret_cast<void (*)(id, SEL, id)>(objc_msgSend)(view, sel_getUid("setLayer:"), nil);
|
reinterpret_cast<void (*)(id, SEL, id)>(objc_msgSend)(view, sel_getUid("setLayer:"), nil);
|
||||||
reinterpret_cast<void (*)(id, SEL, BOOL)>(objc_msgSend)(view, sel_getUid("setWantsLayer:"), NO);
|
reinterpret_cast<void (*)(id, SEL, BOOL)>(objc_msgSend)(view, sel_getUid("setWantsLayer:"), NO);
|
||||||
reinterpret_cast<void (*)(id, SEL)>(objc_msgSend)(layer, sel_getUid("release"));
|
|
||||||
wi->surface_handle = nullptr;
|
wi->surface_handle = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue