From 22ec7e72f0e46fe67d9bd18a334fdfcc935f98e8 Mon Sep 17 00:00:00 2001 From: Samuliak Date: Mon, 8 Apr 2024 16:36:29 +0200 Subject: [PATCH] metal: do not begin render pass if already active --- .../renderer_metal/mtl_command_recorder.cpp | 14 +++++++++----- .../renderer_metal/mtl_command_recorder.h | 9 ++++++--- src/video_core/renderer_metal/mtl_rasterizer.cpp | 2 +- src/video_core/renderer_metal/renderer_metal.cpp | 6 +++--- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/video_core/renderer_metal/mtl_command_recorder.cpp b/src/video_core/renderer_metal/mtl_command_recorder.cpp index 6f09567138..0b0751891f 100644 --- a/src/video_core/renderer_metal/mtl_command_recorder.cpp +++ b/src/video_core/renderer_metal/mtl_command_recorder.cpp @@ -10,11 +10,14 @@ CommandRecorder::CommandRecorder(const Device& device_) : device(device_) {} CommandRecorder::~CommandRecorder() = default; -void CommandRecorder::BeginRenderPass(MTL::RenderPassDescriptor* render_pass) { - RequireCommandBuffer(); - EndEncoding(); - encoder = command_buffer->renderCommandEncoder(render_pass); - encoder_type = EncoderType::Render; +void CommandRecorder::BeginOrContinueRenderPass(MTL::RenderPassDescriptor* render_pass) { + if (render_pass != bound_render_pass) { + RequireCommandBuffer(); + EndEncoding(); + encoder = command_buffer->renderCommandEncoder(render_pass); + encoder_type = EncoderType::Render; + bound_render_pass = render_pass; + } } void CommandRecorder::RequireComputeEncoder() { @@ -40,6 +43,7 @@ void CommandRecorder::EndEncoding() { encoder->endEncoding(); //[encoder release]; encoder = nullptr; + bound_render_pass = nullptr; } } diff --git a/src/video_core/renderer_metal/mtl_command_recorder.h b/src/video_core/renderer_metal/mtl_command_recorder.h index ca7a1128b6..fc04965d86 100644 --- a/src/video_core/renderer_metal/mtl_command_recorder.h +++ b/src/video_core/renderer_metal/mtl_command_recorder.h @@ -20,7 +20,7 @@ public: CommandRecorder(const Device& device_); ~CommandRecorder(); - void BeginRenderPass(MTL::RenderPassDescriptor* render_pass); + void BeginOrContinueRenderPass(MTL::RenderPassDescriptor* render_pass); void CheckIfRenderPassIsActive() { if (!encoder || encoder_type != EncoderType::Render) { @@ -66,11 +66,14 @@ private: // HACK: Command buffers and encoders currently aren't released every frame due to Xcode // crashing in Debug mode. This leads to memory leaks - MTL::CommandBuffer* command_buffer = nil; - MTL::CommandEncoder* encoder = nil; + MTL::CommandBuffer* command_buffer{nullptr}; + MTL::CommandEncoder* encoder{nullptr}; EncoderType encoder_type; + // Keep track of last bound render pass + MTL::RenderPassDescriptor* bound_render_pass{nullptr}; + void RequireCommandBuffer(); }; diff --git a/src/video_core/renderer_metal/mtl_rasterizer.cpp b/src/video_core/renderer_metal/mtl_rasterizer.cpp index 29e8ce3f6f..544f153d99 100644 --- a/src/video_core/renderer_metal/mtl_rasterizer.cpp +++ b/src/video_core/renderer_metal/mtl_rasterizer.cpp @@ -96,7 +96,7 @@ void RasterizerMetal::Clear(u32 layer_count) { } // Begin render pass - command_recorder.BeginRenderPass(framebuffer->GetHandle()); + command_recorder.BeginOrContinueRenderPass(framebuffer->GetHandle()); } void RasterizerMetal::DispatchCompute() { diff --git a/src/video_core/renderer_metal/renderer_metal.cpp b/src/video_core/renderer_metal/renderer_metal.cpp index d1a35df905..3088afd7d5 100644 --- a/src/video_core/renderer_metal/renderer_metal.cpp +++ b/src/video_core/renderer_metal/renderer_metal.cpp @@ -14,8 +14,8 @@ namespace Metal { RendererMetal::RendererMetal(Core::Frontend::EmuWindow& emu_window, Tegra::MaxwellDeviceMemoryManager& device_memory_, Tegra::GPU& gpu_, std::unique_ptr context_) - : RendererBase(emu_window, std::move(context_)), - device_memory{device_memory_}, gpu{gpu_}, device{}, command_recorder(device), + : RendererBase(emu_window, std::move(context_)), device_memory{device_memory_}, gpu{gpu_}, + device{}, command_recorder(device), swap_chain(device, command_recorder, static_cast(render_window.GetWindowInfo().render_surface)), rasterizer(gpu_, device_memory, device, command_recorder, swap_chain) { @@ -42,7 +42,7 @@ void RendererMetal::Composite(std::span framebuf render_pass_descriptor->colorAttachments()->object(0)->setTexture( swap_chain.GetDrawableTexture()); - command_recorder.BeginRenderPass(render_pass_descriptor); + command_recorder.BeginOrContinueRenderPass(render_pass_descriptor); // Blit the framebuffer to the drawable texture // TODO: acquire the texture from @ref framebuffers