From 40ead584d74cf44a425ae36f7caa04a712a74eb8 Mon Sep 17 00:00:00 2001 From: TellowKrinkle Date: Thu, 21 Dec 2023 20:43:02 -0600 Subject: [PATCH] GS:MTL: Properly handle hdr rendering to cleared textures --- pcsx2/GS/Renderers/Metal/GSDeviceMTL.h | 2 +- pcsx2/GS/Renderers/Metal/GSDeviceMTL.mm | 27 ++++++++++++++++++++----- pcsx2/GS/Renderers/Metal/convert.metal | 5 +++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/pcsx2/GS/Renderers/Metal/GSDeviceMTL.h b/pcsx2/GS/Renderers/Metal/GSDeviceMTL.h index 97e5bead2b708..7a5fef90604b4 100644 --- a/pcsx2/GS/Renderers/Metal/GSDeviceMTL.h +++ b/pcsx2/GS/Renderers/Metal/GSDeviceMTL.h @@ -252,11 +252,11 @@ class GSDeviceMTL final : public GSDevice MRCOwned> m_stencil_clear_pipeline; MRCOwned> m_primid_init_pipeline[2][2]; MRCOwned> m_hdr_init_pipeline; + MRCOwned> m_hdr_clear_pipeline; MRCOwned> m_hdr_resolve_pipeline; MRCOwned> m_fxaa_pipeline; MRCOwned> m_shadeboost_pipeline; MRCOwned> m_imgui_pipeline; - MRCOwned> m_imgui_pipeline_a8; MRCOwned> m_hw_vs[1 << 5]; std::unordered_map>> m_hw_ps; diff --git a/pcsx2/GS/Renderers/Metal/GSDeviceMTL.mm b/pcsx2/GS/Renderers/Metal/GSDeviceMTL.mm index 15c5211a966fc..da939f1b139dc 100644 --- a/pcsx2/GS/Renderers/Metal/GSDeviceMTL.mm +++ b/pcsx2/GS/Renderers/Metal/GSDeviceMTL.mm @@ -1043,6 +1043,7 @@ static void OnMainThread(Fn&& fn) m_clut_pipeline[1] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_convert_clut_8"), @"8-bit CLUT Update"); pdesc.colorAttachments[0].pixelFormat = ConvertPixelFormat(GSTexture::Format::HDRColor); m_hdr_init_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_hdr_init"), @"HDR Init"); + m_hdr_clear_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_clear"), @"HDR Clear"); pdesc.colorAttachments[0].pixelFormat = MTLPixelFormatInvalid; pdesc.stencilAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; m_datm_pipeline[0] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_datm0"), @"datm0"); @@ -2139,11 +2140,27 @@ static bool usesStencil(GSHWDrawConfig::DestinationAlphaMode dstalpha) if (config.ps.hdr) { GSVector2i size = config.rt->GetSize(); - hdr_rt = CreateRenderTarget(size.x, size.y, GSTexture::Format::HDRColor); - BeginRenderPass(@"HDR Init", hdr_rt, MTLLoadActionDontCare, nullptr, MTLLoadActionDontCare); - RenderCopy(config.rt, m_hdr_init_pipeline, config.drawarea); - rt = hdr_rt; - g_perfmon.Put(GSPerfMon::TextureCopies, 1); + rt = hdr_rt = CreateRenderTarget(size.x, size.y, GSTexture::Format::HDRColor, false); + switch (config.rt->GetState()) + { + case GSTexture::State::Dirty: + BeginRenderPass(@"HDR Init", hdr_rt, MTLLoadActionDontCare, nullptr, MTLLoadActionDontCare); + RenderCopy(config.rt, m_hdr_init_pipeline, config.drawarea); + g_perfmon.Put(GSPerfMon::TextureCopies, 1); + break; + + case GSTexture::State::Cleared: + { + BeginRenderPass(@"HDR Clear", hdr_rt, MTLLoadActionDontCare, nullptr, MTLLoadActionDontCare); + GSVector4 color = GSVector4::rgba32(config.rt->GetClearColor()) / GSVector4::cxpr(65535, 65535, 65535, 255); + [m_current_render.encoder setFragmentBytes:&color length:sizeof(color) atIndex:GSMTLBufferIndexUniforms]; + RenderCopy(nullptr, m_hdr_clear_pipeline, config.drawarea); + break; + } + + case GSTexture::State::Invalidated: + break; + } } // Try to reduce render pass restarts diff --git a/pcsx2/GS/Renderers/Metal/convert.metal b/pcsx2/GS/Renderers/Metal/convert.metal index 68bfe60162536..470e47bb8125d 100644 --- a/pcsx2/GS/Renderers/Metal/convert.metal +++ b/pcsx2/GS/Renderers/Metal/convert.metal @@ -77,6 +77,11 @@ fragment float4 ps_copy_fs(float4 p [[position]], DirectReadTextureIn tex return tex.read(p); } +fragment float4 ps_clear(float4 p [[position]], constant float4& color [[buffer(GSMTLBufferIndexUniforms)]]) +{ + return color; +} + fragment void ps_datm1(float4 p [[position]], DirectReadTextureIn tex) { if (tex.read(p).a < (127.5f / 255.f))