From fc4036af809fcdfec64d8b8d24b8569ba21f4326 Mon Sep 17 00:00:00 2001 From: TellowKrinkle Date: Tue, 27 Jun 2023 23:50:16 -0500 Subject: [PATCH] VideoBackends:Metal: Multi render target support --- Source/Core/VideoBackends/Metal/MTLGfx.mm | 14 +++--- .../VideoBackends/Metal/MTLObjectCache.mm | 7 +++ .../VideoBackends/Metal/MTLStateTracker.h | 1 - .../VideoBackends/Metal/MTLStateTracker.mm | 35 ++------------ Source/Core/VideoBackends/Metal/MTLTexture.h | 26 +++++++--- Source/Core/VideoBackends/Metal/MTLTexture.mm | 47 ++++++++++++++++++- 6 files changed, 82 insertions(+), 48 deletions(-) diff --git a/Source/Core/VideoBackends/Metal/MTLGfx.mm b/Source/Core/VideoBackends/Metal/MTLGfx.mm index 1137c45e5f..cf3c134cdb 100644 --- a/Source/Core/VideoBackends/Metal/MTLGfx.mm +++ b/Source/Core/VideoBackends/Metal/MTLGfx.mm @@ -94,12 +94,12 @@ Metal::Gfx::CreateStagingTexture(StagingTextureType type, const TextureConfig& c std::unique_ptr Metal::Gfx::CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment, - std::vector) + std::vector additional_color_attachments) { AbstractTexture* const either_attachment = color_attachment ? color_attachment : depth_attachment; return std::make_unique( - color_attachment, depth_attachment, either_attachment->GetWidth(), - either_attachment->GetHeight(), either_attachment->GetLayers(), + color_attachment, depth_attachment, std::move(additional_color_attachments), + either_attachment->GetWidth(), either_attachment->GetHeight(), either_attachment->GetLayers(), either_attachment->GetSamples()); } @@ -437,7 +437,7 @@ void Metal::Gfx::BindBackbuffer(const ClearColor& clear_color) CheckForSurfaceChange(); CheckForSurfaceResize(); m_drawable = MRCRetain([m_layer nextDrawable]); - m_bb_texture->SetMTLTexture(MRCRetain([m_drawable texture])); + m_backbuffer->UpdateBackbufferTexture([m_drawable texture]); SetAndClearFramebuffer(m_backbuffer.get(), clear_color); } } @@ -460,7 +460,7 @@ void Metal::Gfx::PresentBackbuffer() else [g_state_tracker->GetRenderCmdBuf() addScheduledHandler:[drawable = std::move(m_drawable)](id) { [drawable present]; }]; - m_bb_texture->SetMTLTexture(nullptr); + m_backbuffer->UpdateBackbufferTexture(nullptr); m_drawable = nullptr; } g_state_tracker->FlushEncoders(); @@ -491,8 +491,8 @@ void Metal::Gfx::SetupSurface() TextureConfig cfg(info.width, info.height, 1, 1, 1, info.format, AbstractTextureFlag_RenderTarget); m_bb_texture = std::make_unique(nullptr, cfg); - m_backbuffer = std::make_unique(m_bb_texture.get(), nullptr, // - info.width, info.height, 1, 1); + m_backbuffer = std::make_unique( + m_bb_texture.get(), nullptr, std::vector{}, info.width, info.height, 1, 1); if (g_presenter) g_presenter->SetBackbuffer(info); diff --git a/Source/Core/VideoBackends/Metal/MTLObjectCache.mm b/Source/Core/VideoBackends/Metal/MTLObjectCache.mm index 2a9387edeb..5d29f06e88 100644 --- a/Source/Core/VideoBackends/Metal/MTLObjectCache.mm +++ b/Source/Core/VideoBackends/Metal/MTLObjectCache.mm @@ -313,6 +313,8 @@ public: framebuffer.color_texture_format = cfg.framebuffer_state.color_texture_format.Value(); framebuffer.depth_texture_format = cfg.framebuffer_state.depth_texture_format.Value(); framebuffer.samples = cfg.framebuffer_state.samples.Value(); + framebuffer.additional_color_attachment_count = + cfg.framebuffer_state.additional_color_attachment_count.Value(); blend.colorupdate = cfg.blending_state.colorupdate.Value(); blend.alphaupdate = cfg.blending_state.alphaupdate.Value(); if (cfg.blending_state.blendenable) @@ -426,6 +428,11 @@ public: } [desc setRasterSampleCount:fs.samples]; [color0 setPixelFormat:Util::FromAbstract(fs.color_texture_format)]; + if (u32 cnt = fs.additional_color_attachment_count) + { + for (u32 i = 0; i < cnt; i++) + [[desc colorAttachments] setObject:color0 atIndexedSubscript:i + 1]; + } [desc setDepthAttachmentPixelFormat:Util::FromAbstract(fs.depth_texture_format)]; if (Util::HasStencil(fs.depth_texture_format)) [desc setStencilAttachmentPixelFormat:Util::FromAbstract(fs.depth_texture_format)]; diff --git a/Source/Core/VideoBackends/Metal/MTLStateTracker.h b/Source/Core/VideoBackends/Metal/MTLStateTracker.h index 54e16cac7e..f3fa306dd7 100644 --- a/Source/Core/VideoBackends/Metal/MTLStateTracker.h +++ b/Source/Core/VideoBackends/Metal/MTLStateTracker.h @@ -182,7 +182,6 @@ private: MRCOwned> m_last_render_cmdbuf; MRCOwned> m_current_render_encoder; MRCOwned> m_current_compute_encoder; - MRCOwned m_render_pass_desc[3]; MRCOwned m_resolve_pass_desc; Framebuffer* m_current_framebuffer; CPUBuffer m_texture_upload_buffer; diff --git a/Source/Core/VideoBackends/Metal/MTLStateTracker.mm b/Source/Core/VideoBackends/Metal/MTLStateTracker.mm index f699657ade..8546744a4d 100644 --- a/Source/Core/VideoBackends/Metal/MTLStateTracker.mm +++ b/Source/Core/VideoBackends/Metal/MTLStateTracker.mm @@ -107,12 +107,6 @@ Metal::StateTracker::StateTracker() : m_backref(std::make_shared(this)) { m_flags.should_apply_label = true; m_fence = MRCTransfer([g_device newFence]); - for (MRCOwned& rpdesc : m_render_pass_desc) - { - rpdesc = MRCTransfer([MTLRenderPassDescriptor new]); - [[rpdesc depthAttachment] setStoreAction:MTLStoreActionStore]; - [[rpdesc stencilAttachment] setStoreAction:MTLStoreActionStore]; - } m_resolve_pass_desc = MRCTransfer([MTLRenderPassDescriptor new]); auto color0 = [[m_resolve_pass_desc colorAttachments] objectAtIndexedSubscript:0]; [color0 setLoadAction:MTLLoadActionLoad]; @@ -299,27 +293,8 @@ void Metal::StateTracker::SetCurrentFramebuffer(Framebuffer* framebuffer) MTLRenderPassDescriptor* Metal::StateTracker::GetRenderPassDescriptor(Framebuffer* framebuffer, MTLLoadAction load_action) { - const AbstractTextureFormat depth_fmt = framebuffer->GetDepthFormat(); - MTLRenderPassDescriptor* desc; - if (depth_fmt == AbstractTextureFormat::Undefined) - desc = m_render_pass_desc[0]; - else if (!Util::HasStencil(depth_fmt)) - desc = m_render_pass_desc[1]; - else - desc = m_render_pass_desc[2]; - desc.colorAttachments[0].texture = framebuffer->GetColor(); - desc.colorAttachments[0].loadAction = load_action; - if (depth_fmt != AbstractTextureFormat::Undefined) - { - desc.depthAttachment.texture = framebuffer->GetDepth(); - desc.depthAttachment.loadAction = load_action; - if (Util::HasStencil(depth_fmt)) - { - desc.stencilAttachment.texture = framebuffer->GetDepth(); - desc.stencilAttachment.loadAction = load_action; - } - } - return desc; + framebuffer->SetLoadAction(load_action); + return framebuffer->PassDesc(); } void Metal::StateTracker::BeginClearRenderPass(MTLClearColor color, float depth) @@ -328,11 +303,9 @@ void Metal::StateTracker::BeginClearRenderPass(MTLClearColor color, float depth) MTLRenderPassDescriptor* desc = GetRenderPassDescriptor(framebuffer, MTLLoadActionClear); desc.colorAttachments[0].clearColor = color; if (framebuffer->GetDepthFormat() != AbstractTextureFormat::Undefined) - { desc.depthAttachment.clearDepth = depth; - if (Util::HasStencil(framebuffer->GetDepthFormat())) - desc.stencilAttachment.clearStencil = 0; - } + for (size_t i = 0; i < framebuffer->NumAdditionalColorTextures(); i++) + desc.colorAttachments[i + 1].clearColor = color; BeginRenderPass(desc); } diff --git a/Source/Core/VideoBackends/Metal/MTLTexture.h b/Source/Core/VideoBackends/Metal/MTLTexture.h index 0624661414..908f281e04 100644 --- a/Source/Core/VideoBackends/Metal/MTLTexture.h +++ b/Source/Core/VideoBackends/Metal/MTLTexture.h @@ -29,7 +29,6 @@ public: u32 layer) override; id GetMTLTexture() const { return m_tex; } - void SetMTLTexture(MRCOwned> tex) { m_tex = std::move(tex); } private: MRCOwned> m_tex; @@ -61,17 +60,30 @@ private: class Framebuffer final : public AbstractFramebuffer { public: - Framebuffer(AbstractTexture* color, AbstractTexture* depth, u32 width, u32 height, u32 layers, - u32 samples); + Framebuffer(AbstractTexture* color, AbstractTexture* depth, + std::vector additonal_color_textures, // + u32 width, u32 height, u32 layers, u32 samples); ~Framebuffer(); - id GetColor() const + MTLRenderPassDescriptor* PassDesc() const { return m_pass_descriptor; } + + size_t NumAdditionalColorTextures() const { return m_additional_color_textures.size(); } + + void SetLoadAction(MTLLoadAction action) { - return static_cast(GetColorAttachment())->GetMTLTexture(); + if (m_current_load_action != action) + ActualSetLoadAction(action); } - id GetDepth() const + + void UpdateBackbufferTexture(id tex) { - return static_cast(GetDepthAttachment())->GetMTLTexture(); + [m_pass_descriptor colorAttachments][0].texture = tex; } + +private: + MRCOwned m_pass_descriptor; + std::vector m_additional_color_textures; + MTLLoadAction m_current_load_action = MTLLoadActionLoad; + void ActualSetLoadAction(MTLLoadAction action); }; } // namespace Metal diff --git a/Source/Core/VideoBackends/Metal/MTLTexture.mm b/Source/Core/VideoBackends/Metal/MTLTexture.mm index c9750eb1a5..ea4c7fb5ab 100644 --- a/Source/Core/VideoBackends/Metal/MTLTexture.mm +++ b/Source/Core/VideoBackends/Metal/MTLTexture.mm @@ -189,13 +189,56 @@ void Metal::StagingTexture::Flush() m_wait_buffer = nullptr; } -Metal::Framebuffer::Framebuffer(AbstractTexture* color, AbstractTexture* depth, // +static void InitDesc(id desc, AbstractTexture* tex) +{ + [desc setTexture:static_cast(tex)->GetMTLTexture()]; + [desc setLoadAction:MTLLoadActionLoad]; + [desc setStoreAction:MTLStoreActionStore]; +} + +static void InitStencilDesc(MTLRenderPassStencilAttachmentDescriptor* desc, AbstractTexture* tex) +{ + InitDesc(desc, tex); + [desc setClearStencil:0]; +} + +Metal::Framebuffer::Framebuffer(AbstractTexture* color, AbstractTexture* depth, + std::vector additonal_color_textures, // u32 width, u32 height, u32 layers, u32 samples) : AbstractFramebuffer(color, depth, {}, color ? color->GetFormat() : AbstractTextureFormat::Undefined, // depth ? depth->GetFormat() : AbstractTextureFormat::Undefined, // - width, height, layers, samples) + width, height, layers, samples), + m_additional_color_textures(std::move(additonal_color_textures)) { + m_pass_descriptor = MRCTransfer([MTLRenderPassDescriptor new]); + MTLRenderPassDescriptor* desc = m_pass_descriptor; + if (color) + InitDesc(desc.colorAttachments[0], color); + if (depth) + { + InitDesc(desc.depthAttachment, depth); + if (Util::HasStencil(depth->GetFormat())) + InitStencilDesc(desc.stencilAttachment, depth); + } + for (size_t i = 0; i < m_additional_color_textures.size(); i++) + InitDesc(desc.colorAttachments[i + 1], m_additional_color_textures[i]); } Metal::Framebuffer::~Framebuffer() = default; + +void Metal::Framebuffer::ActualSetLoadAction(MTLLoadAction action) +{ + m_current_load_action = action; + AbstractTextureFormat depth_fmt = GetDepthFormat(); + MTLRenderPassDescriptor* desc = m_pass_descriptor; + desc.colorAttachments[0].loadAction = action; + if (depth_fmt != AbstractTextureFormat::Undefined) + { + desc.depthAttachment.loadAction = action; + if (Util::HasStencil(depth_fmt)) + desc.stencilAttachment.loadAction = action; + } + for (size_t i = 0; i < NumAdditionalColorTextures(); i++) + desc.colorAttachments[i + 1].loadAction = action; +}