diff --git a/pcsx2/Frontend/MetalHostDisplay.h b/pcsx2/Frontend/MetalHostDisplay.h index 6698033cbf..aed0b5f5c2 100644 --- a/pcsx2/Frontend/MetalHostDisplay.h +++ b/pcsx2/Frontend/MetalHostDisplay.h @@ -31,6 +31,12 @@ class MetalHostDisplay final : public HostDisplay { + enum class UsePresentDrawable : u8 + { + Never = 0, + Always = 1, + IfVsync = 2, + }; MRCOwned m_view; MRCOwned m_layer; GSMTLDevice m_dev; @@ -39,6 +45,7 @@ class MetalHostDisplay final : public HostDisplay MRCOwned> m_current_drawable; MRCOwned m_pass_desc; u32 m_capture_start_frame; + UsePresentDrawable m_use_present_drawable; bool m_gpu_timing_enabled = false; double m_accumulated_gpu_time = 0; double m_last_gpu_time_end = 0; diff --git a/pcsx2/Frontend/MetalHostDisplay.mm b/pcsx2/Frontend/MetalHostDisplay.mm index 46f8dae67c..e51b567756 100644 --- a/pcsx2/Frontend/MetalHostDisplay.mm +++ b/pcsx2/Frontend/MetalHostDisplay.mm @@ -129,6 +129,13 @@ bool MetalHostDisplay::CreateDevice(const WindowInfo& wi) [m_pass_desc colorAttachments][0].clearColor = MTLClearColorMake(0, 0, 0, 0); [m_pass_desc colorAttachments][0].storeAction = MTLStoreActionStore; + if (char* env = getenv("MTL_USE_PRESENT_DRAWABLE")) + m_use_present_drawable = static_cast(atoi(env)); + else if (@available(macOS 13.0, *)) + m_use_present_drawable = UsePresentDrawable::Always; + else // Before Ventura, presentDrawable acts like vsync is on when windowed + m_use_present_drawable = UsePresentDrawable::IfVsync; + m_capture_start_frame = 0; if (char* env = getenv("MTL_CAPTURE")) { @@ -294,9 +301,17 @@ void MetalHostDisplay::EndPresent() dev->RenderImGui(ImGui::GetDrawData()); dev->EndRenderPass(); if (m_current_drawable) - [dev->m_current_render_cmdbuf addScheduledHandler:[drawable = std::move(m_current_drawable)](id){ - [drawable present]; - }]; + { + const bool use_present_drawable = m_use_present_drawable == UsePresentDrawable::Always || + (m_use_present_drawable == UsePresentDrawable::IfVsync && m_vsync_mode != VsyncMode::Off); + + if (use_present_drawable) + [dev->m_current_render_cmdbuf presentDrawable:m_current_drawable]; + else + [dev->m_current_render_cmdbuf addScheduledHandler:[drawable = std::move(m_current_drawable)](id){ + [drawable present]; + }]; + } dev->FlushEncoders(); dev->FrameCompleted(); m_current_drawable = nullptr;