diff --git a/src/core/gpu/metal_device.h b/src/core/gpu/metal_device.h index f0910eac2..e668dee44 100644 --- a/src/core/gpu/metal_device.h +++ b/src/core/gpu/metal_device.h @@ -192,7 +192,7 @@ public: AdapterAndModeList GetAdapterAndModeList() override; void DestroySurface() override; - std::string GetShaderCacheBaseName(const std::string_view& type, bool debug) const override; + std::string GetShaderCacheBaseName(const std::string_view& type) const override; std::unique_ptr CreateTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples, GPUTexture::Type type, GPUTexture::Format format, @@ -274,7 +274,7 @@ public: static AdapterAndModeList StaticGetAdapterAndModeList(); protected: - bool CreateDevice(const std::string_view& adapter, bool debug_device) override; + bool CreateDevice(const std::string_view& adapter) override; void DestroyDevice() override; private: @@ -319,6 +319,7 @@ private: bool CreateLayer(); void DestroyLayer(); + void RenderBlankFrame(); bool CreateBuffers(); void DestroyBuffers(); diff --git a/src/core/gpu/metal_device.mm b/src/core/gpu/metal_device.mm index 5c4f567de..8e402efe3 100644 --- a/src/core/gpu/metal_device.mm +++ b/src/core/gpu/metal_device.mm @@ -113,7 +113,7 @@ void MetalDevice::SetVSync(bool enabled) [m_layer setDisplaySyncEnabled:enabled]; } -bool MetalDevice::CreateDevice(const std::string_view& adapter, bool debug_device) +bool MetalDevice::CreateDevice(const std::string_view& adapter) { @autoreleasepool { @@ -142,8 +142,7 @@ bool MetalDevice::CreateDevice(const std::string_view& adapter, bool debug_devic return false; CreateCommandBuffer(); - - Panic("Render blank frame!"); + RenderBlankFrame(); if (!CreateBuffers()) { @@ -277,6 +276,23 @@ void MetalDevice::DestroyLayer() }); } +void MetalDevice::RenderBlankFrame() +{ + DebugAssert(!InRenderPass()); + if (m_layer == nil) + return; + + @autoreleasepool + { + id drawable = [m_layer nextDrawable]; + m_layer_pass_desc.colorAttachments[0].texture = [drawable texture]; + id encoder = [m_render_cmdbuf renderCommandEncoderWithDescriptor:m_layer_pass_desc]; + [encoder endEncoding]; + [m_render_cmdbuf presentDrawable:drawable]; + SubmitCommandBuffer(); + } +} + bool MetalDevice::UpdateWindow() { if (InRenderPass()) @@ -300,9 +316,9 @@ void MetalDevice::DestroySurface() DestroyLayer(); } -std::string MetalDevice::GetShaderCacheBaseName(const std::string_view& type, bool debug) const +std::string MetalDevice::GetShaderCacheBaseName(const std::string_view& type) const { - return fmt::format("metal_{}{}", type, debug ? "_debug" : ""); + return fmt::format("metal_{}{}", type, m_debug_device ? "_debug" : ""); } void MetalDevice::ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale) @@ -1374,6 +1390,30 @@ void MetalDevice::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u3 #endif } +void MetalDevice::ClearRenderTarget(GPUTexture* t, u32 c) +{ + GPUDevice::ClearRenderTarget(t, c); + if (InRenderPass() && m_current_framebuffer && m_current_framebuffer->GetRT() == t) + EndRenderPass(); +} + +void MetalDevice::ClearDepth(GPUTexture* t, float d) +{ + GPUDevice::ClearDepth(t, d); + if (InRenderPass() && m_current_framebuffer && m_current_framebuffer->GetDS() == t) + EndRenderPass(); +} + +void MetalDevice::InvalidateRenderTarget(GPUTexture* t) +{ + GPUDevice::InvalidateRenderTarget(t); + if (InRenderPass() && m_current_framebuffer && + (m_current_framebuffer->GetRT() == t || m_current_framebuffer->GetDS() == t)) + { + EndRenderPass(); + } +} + void MetalDevice::CommitClear(MetalTexture* tex) { if (tex->GetState() == GPUTexture::State::Dirty) @@ -1881,6 +1921,7 @@ void MetalDevice::EndPresent() [m_render_cmdbuf presentDrawable:m_layer_drawable]; [m_layer_drawable release]; + m_layer_drawable = nil; SubmitCommandBuffer(); } diff --git a/src/core/system.cpp b/src/core/system.cpp index fb009984a..06280260f 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -2211,6 +2211,7 @@ void System::DoRunFrame() // Generate any pending samples from the SPU before sleeping, this way we reduce the chances of underruns. SPU::GeneratePendingSamples(); + g_gpu->RestoreGraphicsAPIState(); g_gpu->FlushRender(); if (s_cheat_list) @@ -2283,7 +2284,7 @@ void System::Throttle() // Use a spinwait if we undersleep for all platforms except android.. don't want to burn battery. // Linux also seems to do a much better job of waking up at the requested time. -#if !defined(__linux__) && !defined(__ANDROID__) +#if !defined(__linux__) && !defined(__ANDROID__) && !defined(__APPLE__) Common::Timer::SleepUntil(s_next_frame_time, g_settings.display_all_frames); #else Common::Timer::SleepUntil(s_next_frame_time, false);