GS:MTL: Properly handle hdr rendering to cleared textures

This commit is contained in:
TellowKrinkle 2023-12-21 20:43:02 -06:00 committed by Connor McLaughlin
parent 6f2be7bd17
commit 40ead584d7
3 changed files with 28 additions and 6 deletions

View File

@ -252,11 +252,11 @@ public:
MRCOwned<id<MTLRenderPipelineState>> m_stencil_clear_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_primid_init_pipeline[2][2];
MRCOwned<id<MTLRenderPipelineState>> m_hdr_init_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_hdr_clear_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_hdr_resolve_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_fxaa_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_shadeboost_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_imgui_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_imgui_pipeline_a8;
MRCOwned<id<MTLFunction>> m_hw_vs[1 << 5];
std::unordered_map<PSSelector, MRCOwned<id<MTLFunction>>> m_hw_ps;

View File

@ -1043,6 +1043,7 @@ bool GSDeviceMTL::Create()
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 @@ void GSDeviceMTL::RenderHW(GSHWDrawConfig& config)
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

View File

@ -77,6 +77,11 @@ fragment float4 ps_copy_fs(float4 p [[position]], DirectReadTextureIn<float> 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<float> tex)
{
if (tex.read(p).a < (127.5f / 255.f))