Skip to content

Commit

Permalink
GS/HW: Support for RTA correction.
Browse files Browse the repository at this point in the history
Copy the rt and change it's AD value then copy it back to the rt.
  • Loading branch information
lightningterror committed Feb 23, 2024
1 parent f00f0cc commit f21140c
Show file tree
Hide file tree
Showing 19 changed files with 177 additions and 27 deletions.
16 changes: 16 additions & 0 deletions bin/resources/shaders/dx11/convert.fx
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,22 @@ PS_OUTPUT ps_datm0(PS_INPUT input)
return output;
}

PS_OUTPUT ps_rta_correction(PS_INPUT input)
{
PS_OUTPUT output;
float4 value = sample_c(input.t);
output.c = float4(value.rgb, trunc(value.a * 255 + 0.1) / 128);
return output;
}

PS_OUTPUT ps_rta_decorrection(PS_INPUT input)
{
PS_OUTPUT output;
float4 value = sample_c(input.t);
output.c = float4(value.rgb, (value.a * 128) / 255);
return output;
}

PS_OUTPUT ps_hdr_init(PS_INPUT input)
{
PS_OUTPUT output;
Expand Down
4 changes: 3 additions & 1 deletion bin/resources/shaders/dx11/tfx.fx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#define PS_TALES_OF_ABYSS_HLE 0
#define PS_URBAN_CHAOS_HLE 0
#define PS_HDR 0
#define PS_RTA_CORRECTION 0
#define PS_COLCLIP 0
#define PS_BLEND_A 0
#define PS_BLEND_B 0
Expand Down Expand Up @@ -1069,7 +1070,8 @@ PS_OUTPUT ps_main(PS_INPUT input)
ps_fbmask(C, input.p.xy);

#if !PS_NO_COLOR
output.c0 = PS_HDR ? float4(C.rgb / 65535.0f, C.a / 255.0f) : C / 255.0f;
output.c0.a = PS_RTA_CORRECTION ? C.a / 128.0f : C.a / 255.0f;
output.c0.rgb = PS_HDR ? float3(C.rgb / 65535.0f) : C.rgb / 255.0f;
#if !PS_NO_COLOR1
output.c1 = alpha_blend;
#endif
Expand Down
16 changes: 16 additions & 0 deletions bin/resources/shaders/opengl/convert.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,22 @@ void ps_datm0()
}
#endif

#ifdef ps_rta_correction
void ps_rta_correction()
{
vec4 value = sample_c();
SV_Target0 = vec4(value.rgb, trunc(value.a * 255 + 0.1) / 128);
}
#endif

#ifdef ps_rta_decorrection
void ps_rta_decorrection()
{
vec4 value = sample_c(v_tex);
o_col0 = vec4(value.rgb, value.a * 128 / 255);
}
#endif

#ifdef ps_hdr_init
void ps_hdr_init()
{
Expand Down
9 changes: 7 additions & 2 deletions bin/resources/shaders/opengl/tfx_fs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -1063,10 +1063,15 @@ void ps_main()
ps_fbmask(C);

#if !PS_NO_COLOR
#if PS_RTA_CORRECTION
SV_Target0.a = C.a / 128.0f;
#else
SV_Target0.a = C.a / 255.0f;
#endif
#if PS_HDR == 1
SV_Target0 = vec4(C.rgb / 65535.0f, C.a / 255.0f);
SV_Target0.rgb = vec3(C.rgb / 65535.0f);
#else
SV_Target0 = C / 255.0f;
SV_Target0.rgb = C.rgb / 255.0f;
#endif
#if !defined(DISABLE_DUAL_SOURCE) && !PS_NO_COLOR1
SV_Target1 = alpha_blend;
Expand Down
16 changes: 16 additions & 0 deletions bin/resources/shaders/vulkan/convert.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,22 @@ void ps_datm0()
}
#endif

#ifdef ps_rta_correction
void ps_rta_correction()
{
vec4 value = sample_c(v_tex);
o_col0 = vec4(value.rgb, trunc(value.a * 255 + 0.1) / 128);
}
#endif

#ifdef ps_rta_decorrection
void ps_rta_decorrection()
{
vec4 value = sample_c(v_tex);
o_col0 = vec4(value.rgb, value.a * 128 / 255);
}
#endif

#ifdef ps_hdr_init
void ps_hdr_init()
{
Expand Down
9 changes: 7 additions & 2 deletions bin/resources/shaders/vulkan/tfx.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -1294,10 +1294,15 @@ void main()
ps_fbmask(C);

#if !PS_NO_COLOR
#if PS_RTA_CORRECTION
o_col0.a = C.a / 128.0f;
#else
o_col0.a = C.a / 255.0f;
#endif
#if PS_HDR == 1
o_col0 = vec4(C.rgb / 65535.0f, C.a / 255.0f);
o_col0.rgb = vec3(C.rgb / 65535.0f);
#else
o_col0 = C / 255.0f;
o_col0.rgb = C.rgb / 255.0f;
#endif
#if !defined(DISABLE_DUAL_SOURCE) && !PS_NO_COLOR1
o_col1 = alpha_blend;
Expand Down
2 changes: 2 additions & 0 deletions pcsx2/GS/Renderers/Common/GSDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ const char* shaderName(ShaderConvert value)
case ShaderConvert::DATM_0: return "ps_datm0";
case ShaderConvert::HDR_INIT: return "ps_hdr_init";
case ShaderConvert::HDR_RESOLVE: return "ps_hdr_resolve";
case ShaderConvert::RTA_CORRECTION: return "ps_rta_correction";
case ShaderConvert::RTA_DECORRECTION: return "ps_rta_decorrection";
case ShaderConvert::TRANSPARENCY_FILTER: return "ps_filter_transparency";
case ShaderConvert::FLOAT32_TO_16_BITS: return "ps_convert_float32_32bits";
case ShaderConvert::FLOAT32_TO_32_BITS: return "ps_convert_float32_32bits";
Expand Down
35 changes: 19 additions & 16 deletions pcsx2/GS/Renderers/Common/GSDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ enum class ShaderConvert
DATM_0,
HDR_INIT,
HDR_RESOLVE,
RTA_CORRECTION,
RTA_DECORRECTION,
TRANSPARENCY_FILTER,
FLOAT32_TO_16_BITS,
FLOAT32_TO_32_BITS,
Expand Down Expand Up @@ -307,22 +309,23 @@ struct alignas(16) GSHWDrawConfig
u32 fbmask : 1;

// Blend and Colclip
u32 blend_a : 2;
u32 blend_b : 2;
u32 blend_c : 2;
u32 blend_d : 2;
u32 fixed_one_a : 1;
u32 blend_hw : 2;
u32 a_masked : 1;
u32 hdr : 1;
u32 colclip : 1;
u32 blend_mix : 2;
u32 round_inv : 1; // Blending will invert the value, so rounding needs to go the other way
u32 pabe : 1;
u32 no_color : 1; // disables color output entirely (depth only)
u32 no_color1 : 1; // disables second color output (when unnecessary)
u32 no_ablend : 1; // output alpha blend in col0 (for no-DSB)
u32 only_alpha : 1; // don't bother computing RGB
u32 blend_a : 2;
u32 blend_b : 2;
u32 blend_c : 2;
u32 blend_d : 2;
u32 fixed_one_a : 1;
u32 blend_hw : 2;
u32 a_masked : 1;
u32 hdr : 1;
u32 rta_correction : 1;
u32 colclip : 1;
u32 blend_mix : 2;
u32 round_inv : 1; // Blending will invert the value, so rounding needs to go the other way
u32 pabe : 1;
u32 no_color : 1; // disables color output entirely (depth only)
u32 no_color1 : 1; // disables second color output (when unnecessary)
u32 no_ablend : 1; // output alpha blend in col0 (for no-DSB)
u32 only_alpha : 1; // don't bother computing RGB

// Others ways to fetch the texture
u32 channel : 3;
Expand Down
1 change: 1 addition & 0 deletions pcsx2/GS/Renderers/DX11/GSDevice11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1688,6 +1688,7 @@ void GSDevice11::SetupPS(const PSSelector& sel, const GSHWDrawConfig::PSConstant
sm.AddMacro("PS_DEPTH_FMT", sel.depth_fmt);
sm.AddMacro("PS_PAL_FMT", sel.pal_fmt);
sm.AddMacro("PS_HDR", sel.hdr);
sm.AddMacro("PS_RTA_CORRECTION", sel.rta_correction);
sm.AddMacro("PS_COLCLIP", sel.colclip);
sm.AddMacro("PS_BLEND_A", sel.blend_a);
sm.AddMacro("PS_BLEND_B", sel.blend_b);
Expand Down
1 change: 1 addition & 0 deletions pcsx2/GS/Renderers/DX12/GSDevice12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2814,6 +2814,7 @@ const ID3DBlob* GSDevice12::GetTFXPixelShader(const GSHWDrawConfig::PSSelector&
sm.AddMacro("PS_DEPTH_FMT", sel.depth_fmt);
sm.AddMacro("PS_PAL_FMT", sel.pal_fmt);
sm.AddMacro("PS_HDR", sel.hdr);
sm.AddMacro("PS_RTA_CORRECTION", sel.rta_correction);
sm.AddMacro("PS_COLCLIP", sel.colclip);
sm.AddMacro("PS_BLEND_A", sel.blend_a);
sm.AddMacro("PS_BLEND_B", sel.blend_b);
Expand Down
30 changes: 26 additions & 4 deletions pcsx2/GS/Renderers/HW/GSRendererHW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3691,7 +3691,7 @@ __ri bool GSRendererHW::EmulateChannelShuffle(GSTextureCache::Target* src, bool
return true;
}

void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DATE_PRIMID, bool& DATE_BARRIER, bool& blending_alpha_pass)
void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DATE_PRIMID, bool& DATE_BARRIER, bool& blending_alpha_pass, GSTextureCache::Target* rt)
{
{
// AA1: Blending needs to be enabled on draw.
Expand Down Expand Up @@ -3863,7 +3863,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
const bool one_barrier = m_conf.require_one_barrier || blend_ad_alpha_masked;

// Blend can be done on hw. As and F cases should be accurate.
// BLEND_HW_CLR1 with Ad, BLEND_HW_CLR3 Cs > 0.5f will require sw blend.
// BLEND_HW_CLR1 with Ad, BLEND_HW_CLR3 might require sw blend.
// BLEND_HW_CLR1 with As/F and BLEND_HW_CLR2 can be done in hw.
const bool clr_blend = !!(blend_flag & (BLEND_HW_CLR1 | BLEND_HW_CLR2 | BLEND_HW_CLR3));
bool clr_blend1_2 = (blend_flag & (BLEND_HW_CLR1 | BLEND_HW_CLR2)) && (m_conf.ps.blend_c != 1) && !blend_ad_improved // Make sure it isn't an Ad case
Expand Down Expand Up @@ -4121,6 +4121,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
m_conf.ps.blend_a, m_conf.ps.blend_b, m_conf.ps.blend_c, m_conf.ps.blend_d,
m_env.COLCLAMP.CLAMP, m_vt.m_primclass, m_vertex.next, m_drawlist.size(), sw_blending);
#endif

if (color_dest_blend)
{
// Blend output will be Cd, disable hw/sw blending.
Expand Down Expand Up @@ -4276,6 +4277,16 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
m_conf.ps.blend_b = 0;
m_conf.ps.blend_d = 0;

// TODO: Make it work on DATE, switch to new shaders with Ad doubled.
const bool rta_decorrection = m_channel_shuffle || m_texture_shuffle || rt_alpha_max > 128;
const bool rta_correction = !rta_decorrection && !m_cached_ctx.TEST.DATE && !blend_ad_alpha_masked && m_conf.ps.blend_c == 1;
if (rta_correction)
{
rt->RTACorrect(rt);
m_conf.ps.rta_correction = rt->m_rt_alpha_scale && m_conf.colormask.wa;
m_conf.rt = rt->m_texture;
}

// Care for hw blend value, 6 is for hw/sw, sw blending used.
if (blend_flag & BLEND_HW_CLR1)
{
Expand All @@ -4288,7 +4299,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT

m_conf.ps.blend_hw = 2;
}
else if (blend_flag & BLEND_HW_CLR3)
else if (!rta_correction && (blend_flag & BLEND_HW_CLR3))
{
m_conf.ps.blend_hw = 3;
}
Expand Down Expand Up @@ -5265,11 +5276,22 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
ds->m_alpha_min &= 128;
}
}

{
const bool rta_decorrection = m_channel_shuffle || m_texture_shuffle || blend_alpha_max > 128;
if (rt && rta_decorrection)
{
rt->RTADecorrect(rt);
m_conf.rt = rt->m_texture;
}
else if (rt)
m_conf.ps.rta_correction = rt->m_rt_alpha_scale && m_conf.colormask.wa;
}

bool blending_alpha_pass = false;
if ((!IsOpaque() || m_context->ALPHA.IsBlack()) && rt && ((m_conf.colormask.wrgba & 0x7) || (m_texture_shuffle && !m_copy_16bit_to_target_shuffle && !m_same_group_texture_shuffle)))
{
EmulateBlending(blend_alpha_min, blend_alpha_max, DATE_PRIMID, DATE_BARRIER, blending_alpha_pass);
EmulateBlending(blend_alpha_min, blend_alpha_max, DATE_PRIMID, DATE_BARRIER, blending_alpha_pass, rt);
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion pcsx2/GS/Renderers/HW/GSRendererHW.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class GSRendererHW : public GSRenderer
void SetupIA(float target_scale, float sx, float sy);
void EmulateTextureShuffleAndFbmask(GSTextureCache::Target* rt, GSTextureCache::Source* tex);
bool EmulateChannelShuffle(GSTextureCache::Target* src, bool test_only);
void EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DATE_PRIMID, bool& DATE_BARRIER, bool& blending_alpha_pass);
void EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DATE_PRIMID, bool& DATE_BARRIER, bool& blending_alpha_pass, GSTextureCache::Target* rt);
void CleanupDraw(bool invalidate_temp_src);

void EmulateTextureSampler(const GSTextureCache::Target* rt, const GSTextureCache::Target* ds,
Expand Down
40 changes: 40 additions & 0 deletions pcsx2/GS/Renderers/HW/GSTextureCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1687,6 +1687,10 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
GL_CACHE("TC: src miss (0x%x, 0x%x, %s)", TEX0.TBP0, psm_s.pal > 0 ? TEX0.CBP : 0, psm_str(TEX0.PSM));
}
#endif

if (dst && dst->m_rt_alpha_scale)
dst->RTADecorrect(dst);

src = CreateSource(TEX0, TEXA, dst, half_right, x_offset, y_offset, lod, &r, gpu_clut, region);
if (!src) [[unlikely]]
return nullptr;
Expand Down Expand Up @@ -2643,6 +2647,42 @@ GSTextureCache::Target* GSTextureCache::LookupDisplayTarget(GIFRegTEX0 TEX0, con
return can_create ? CreateTarget(TEX0, size, size, scale, RenderTarget, true, 0, true) : nullptr;
}

void GSTextureCache::Target::RTACorrect(Target* rt)
{
if (!rt->m_rt_alpha_scale)
{
const GSVector4 rtsize(rt->m_texture->GetSize());
if (GSTexture* temp_rt = g_gs_device->CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::Color, false))
{
const GSVector4 dRect(rt->m_texture->GetRect());
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
g_gs_device->StretchRect(rt->m_texture, sRect, temp_rt, dRect, ShaderConvert::RTA_CORRECTION, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
g_gs_device->Recycle(rt->m_texture);
rt->m_texture = temp_rt;
rt->m_rt_alpha_scale = true;
}
}
}

void GSTextureCache::Target::RTADecorrect(Target* rt)
{
if (rt->m_rt_alpha_scale)
{
const GSVector4 rtsize(rt->m_texture->GetSize());
if (GSTexture* temp_rt = g_gs_device->CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::Color, false))
{
const GSVector4 dRect(rt->m_texture->GetRect());
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
g_gs_device->StretchRect(rt->m_texture, sRect, temp_rt, dRect, ShaderConvert::RTA_DECORRECTION, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
g_gs_device->Recycle(rt->m_texture);
rt->m_texture = temp_rt;
rt->m_rt_alpha_scale = false;
}
}
}

void GSTextureCache::ScaleTargetForDisplay(Target* t, const GIFRegTEX0& dispfb, int real_w, int real_h)
{
// This handles a case where you have two images stacked on top of one another (usually FMVs), and
Expand Down
4 changes: 4 additions & 0 deletions pcsx2/GS/Renderers/HW/GSTextureCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ class GSTextureCache
bool m_valid_alpha_low = false;
bool m_valid_alpha_high = false;
bool m_valid_rgb = false;
bool m_rt_alpha_scale = false;

bool m_is_frame = false;
bool m_used = false;
Expand All @@ -237,6 +238,9 @@ class GSTextureCache
void ResizeValidity(const GSVector4i& rect);
void UpdateValidity(const GSVector4i& rect, bool can_resize = true);

void RTACorrect(Target* rt);
void RTADecorrect(Target* rt);

void Update();

/// Updates the target, if the dirty area intersects with the specified rectangle.
Expand Down
1 change: 1 addition & 0 deletions pcsx2/GS/Renderers/Metal/GSDeviceMTL.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1810,6 +1810,7 @@ static GSMTLExpandType ConvertVSExpand(GSHWDrawConfig::VSExpand generic)
setFnConstantI(m_fn_constants, pssel.blend_hw, GSMTLConstantIndex_PS_BLEND_HW);
setFnConstantB(m_fn_constants, pssel.a_masked, GSMTLConstantIndex_PS_A_MASKED);
setFnConstantB(m_fn_constants, pssel.hdr, GSMTLConstantIndex_PS_HDR);
setFnConstantB(m_fn_constants, pssel.rta_correction, GSMTLConstantIndex_PS_RTA_CORRECTION);
setFnConstantB(m_fn_constants, pssel.colclip, GSMTLConstantIndex_PS_COLCLIP);
setFnConstantI(m_fn_constants, pssel.blend_mix, GSMTLConstantIndex_PS_BLEND_MIX);
setFnConstantB(m_fn_constants, pssel.round_inv, GSMTLConstantIndex_PS_ROUND_INV);
Expand Down
12 changes: 12 additions & 0 deletions pcsx2/GS/Renderers/Metal/convert.metal
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,18 @@ fragment float4 ps_primid_init_datm1(float4 p [[position]], DirectReadTextureIn<
return tex.read(p).a < (127.5f / 255.f) ? -1 : FLT_MAX;
}

fragment float4 ps_rta_correction(float4 p [[position]], DirectReadTextureIn<float> tex)
{
float4 in = tex.read(p);
return float4(in.rgb, trunc(in.a * 255 + 0.1) / 128);
}

fragment float4 ps_rta_decorrection(float4 p [[position]], DirectReadTextureIn<float> tex)
{
float4 in = tex.read(p);
return float4(in.rgb, in.a * 128 / 255);
}

fragment float4 ps_hdr_init(float4 p [[position]], DirectReadTextureIn<float> tex)
{
float4 in = tex.read(p);
Expand Down
4 changes: 3 additions & 1 deletion pcsx2/GS/Renderers/Metal/tfx.metal
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ constant uint PS_BLEND_D [[function_constant(GSMTLConstantIndex_PS_BL
constant uint PS_BLEND_HW [[function_constant(GSMTLConstantIndex_PS_BLEND_HW)]];
constant bool PS_A_MASKED [[function_constant(GSMTLConstantIndex_PS_A_MASKED)]];
constant bool PS_HDR [[function_constant(GSMTLConstantIndex_PS_HDR)]];
constant bool PS_RTA_CORRECTION [[function_constant(GSMTLConstantIndex_PS_RTA_CORRECTION)]];
constant bool PS_COLCLIP [[function_constant(GSMTLConstantIndex_PS_COLCLIP)]];
constant uint PS_BLEND_MIX [[function_constant(GSMTLConstantIndex_PS_BLEND_MIX)]];
constant bool PS_ROUND_INV [[function_constant(GSMTLConstantIndex_PS_ROUND_INV)]];
Expand Down Expand Up @@ -1121,7 +1122,8 @@ struct PSMain
ps_fbmask(C);

if (PS_COLOR0)
out.c0 = PS_HDR ? float4(C.rgb / 65535.f, C.a / 255.f) : C / 255.f;
out.c0.a = PS_RTA_CORRECTION ? C.a / 128.f : C.a / 255.f;
out.c0.rgb = PS_HDR ? float3(C.rgb / 65535.f) : C.rgb / 255.f;
if (PS_COLOR0 && PS_ONLY_ALPHA)
out.c0.rgb = 0;
if (PS_COLOR1)
Expand Down
Loading

0 comments on commit f21140c

Please sign in to comment.