diff --git a/pcsx2/GS/GSState.h b/pcsx2/GS/GSState.h index 3bb058497b..201acee109 100644 --- a/pcsx2/GS/GSState.h +++ b/pcsx2/GS/GSState.h @@ -216,7 +216,6 @@ public: bool m_texflush_flag = false; bool m_isPackedUV_HackFlag = false; bool m_channel_shuffle = false; - bool m_can_correct_alpha = false; u8 m_scanmask_used = 0; u32 m_dirty_gs_regs = 0; int m_backed_up_ctx = 0; diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index d97d1266d9..ac375c2928 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -3869,7 +3869,8 @@ __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, GSTextureCache::Target* rt) +void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DATE_PRIMID, bool& DATE_BARRIER, + GSTextureCache::Target* rt, bool can_scale_rt_alpha, bool& new_rt_alpha_scale) { { // AA1: Blending needs to be enabled on draw. @@ -3941,7 +3942,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT const bool alpha_c0_less_max_one = (m_conf.ps.blend_c == 0 && GetAlphaMinMax().max <= 128); const bool alpha_c1_high_min_one = (m_conf.ps.blend_c == 1 && rt_alpha_min > 128); const bool alpha_c1_high_max_one = (m_conf.ps.blend_c == 1 && rt_alpha_max > 128); - const bool alpha_c1_high_no_rta_correct = m_conf.ps.blend_c == 1 && !(rt->m_rt_alpha_scale || m_can_correct_alpha); + const bool alpha_c1_high_no_rta_correct = m_conf.ps.blend_c == 1 && !(new_rt_alpha_scale || can_scale_rt_alpha); const bool alpha_c2_zero = (m_conf.ps.blend_c == 2 && AFIX == 0u); const bool alpha_c2_one = (m_conf.ps.blend_c == 2 && AFIX == 128u); const bool alpha_c2_less_one = (m_conf.ps.blend_c == 2 && AFIX <= 128u); @@ -4397,7 +4398,7 @@ 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; - const bool rta_correction = m_can_correct_alpha && !blend_ad_alpha_masked && m_conf.ps.blend_c == 1 && !(blend_flag & BLEND_A_MAX); + const bool rta_correction = can_scale_rt_alpha && !blend_ad_alpha_masked && m_conf.ps.blend_c == 1 && !(blend_flag & BLEND_A_MAX); if (rta_correction) { const bool afail_always_fb_alpha = m_cached_ctx.TEST.AFAIL == AFAIL_FB_ONLY || (m_cached_ctx.TEST.AFAIL == AFAIL_RGB_ONLY && GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].trbpp != 32); @@ -4409,8 +4410,8 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT rt->RTACorrect(); m_conf.rt = rt->m_texture; } - else - rt->m_rt_alpha_scale = true; + + new_rt_alpha_scale = true; m_conf.ps.rta_correction = rt->m_rt_alpha_scale; } @@ -5317,6 +5318,8 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta int rt_new_alpha_min = 0, rt_new_alpha_max = 255; if (rt) { + GL_INS("RT alpha was %s before draw", rt->m_rt_alpha_scale ? "scaled" : "NOT scaled"); + blend_alpha_min = rt_new_alpha_min = rt->m_alpha_min; blend_alpha_max = rt_new_alpha_max = rt->m_alpha_max; @@ -5536,10 +5539,14 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta // If we Correct/Decorrect and tex is rt, we will need to update the texture reference const bool req_src_update = tex && rt && tex->m_target && tex->m_target_direct && tex->m_texture == rt->m_texture; - m_can_correct_alpha = !needs_ad && (GSUtil::GetChannelMask(m_cached_ctx.FRAME.PSM) & 0x8) && rt_new_alpha_max <= 128; - + // We defer updating the alpha scaled flag until after the texture setup if we're scaling as part of the draw, + // because otherwise we'll treat tex-is-fb as a scaled source, when it's not yet. + bool can_scale_rt_alpha = false; + bool new_scale_rt_alpha = false; if (rt) { + can_scale_rt_alpha = !needs_ad && (GSUtil::GetChannelMask(m_cached_ctx.FRAME.PSM) & 0x8) && rt_new_alpha_max <= 128; + const bool partial_fbmask = (m_conf.ps.fbmask && m_conf.cb_ps.FbMask.a != 0xFF && m_conf.cb_ps.FbMask.a != 0); const bool rta_decorrection = m_channel_shuffle || m_texture_shuffle || (m_conf.colormask.wa && (rt_new_alpha_max > 128 || partial_fbmask)); @@ -5549,7 +5556,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta { if (m_conf.ps.process_ba & SHUFFLE_READ) { - m_can_correct_alpha = false; + can_scale_rt_alpha = false; rt->RTADecorrect(); m_conf.rt = rt->m_texture; @@ -5561,12 +5568,12 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta { if (!(m_cached_ctx.FRAME.FBMSK & 0xFFFC0000)) { - m_can_correct_alpha = false; + can_scale_rt_alpha = false; rt->m_rt_alpha_scale = false; } else if (m_cached_ctx.FRAME.FBMSK & 0xFFFC0000) { - m_can_correct_alpha = false; + can_scale_rt_alpha = false; rt->RTADecorrect(); m_conf.rt = rt->m_texture; @@ -5579,7 +5586,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta { if (m_conf.ps.tales_of_abyss_hle || (tex && tex->m_from_target && tex->m_from_target == rt && m_conf.ps.channel == ChannelFetch_ALPHA) || partial_fbmask || rt_new_alpha_max > 128) { - m_can_correct_alpha = false; + can_scale_rt_alpha = false; rt->RTADecorrect(); m_conf.rt = rt->m_texture; @@ -5589,12 +5596,12 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta } else if (rt->m_last_draw == s_n) { - m_can_correct_alpha = false; + can_scale_rt_alpha = false; rt->m_rt_alpha_scale = false; } else { - m_can_correct_alpha = false; + can_scale_rt_alpha = false; rt->RTADecorrect(); m_conf.rt = rt->m_texture; @@ -5602,37 +5609,27 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta tex->m_texture = rt->m_texture; } } - else if (!rt->m_rt_alpha_scale) - m_can_correct_alpha = m_can_correct_alpha; - m_conf.ps.rta_correction = rt->m_rt_alpha_scale; + new_scale_rt_alpha = rt->m_rt_alpha_scale; } 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, rt); + EmulateBlending(blend_alpha_min, blend_alpha_max, DATE_PRIMID, DATE_BARRIER, rt, can_scale_rt_alpha, new_scale_rt_alpha); } else { m_conf.blend = {}; // No blending please m_conf.ps.no_color1 = true; - // Try to avoid palette draws - if (rt && m_can_correct_alpha && !rt->m_rt_alpha_scale && rt->m_alpha_max == rt->m_alpha_min ) + if (can_scale_rt_alpha && !new_scale_rt_alpha && m_conf.colormask.wa) { const bool afail_always_fb_alpha = m_cached_ctx.TEST.AFAIL == AFAIL_FB_ONLY || (m_cached_ctx.TEST.AFAIL == AFAIL_RGB_ONLY && GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].trbpp != 32); const bool always_passing_alpha = !m_cached_ctx.TEST.ATE || afail_always_fb_alpha || (m_cached_ctx.TEST.ATE && m_cached_ctx.TEST.ATST == ATST_ALWAYS); const bool full_cover = rt->m_valid.rintersect(m_r).eq(rt->m_valid) && PrimitiveCoversWithoutGaps() && !(DATE || !always_passing_alpha || !IsDepthAlwaysPassing()); - if (!full_cover) - { - rt->RTACorrect(); - m_conf.rt = rt->m_texture; - } - else - rt->m_rt_alpha_scale = true; - - m_conf.ps.rta_correction = rt->m_rt_alpha_scale; + // Restrict this to only when we're overwriting the whole target. + new_scale_rt_alpha = full_cover; } } @@ -5750,7 +5747,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta else if (features.stencil_buffer) m_conf.destination_alpha = GSHWDrawConfig::DestinationAlphaMode::Stencil; - if (m_conf.ps.rta_correction) + if (new_scale_rt_alpha) m_conf.datm = static_cast(m_cached_ctx.TEST.DATM + 2); else m_conf.datm = static_cast(m_cached_ctx.TEST.DATM); @@ -5873,6 +5870,14 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta m_conf.ps.tfx = 4; } + // Update RT scaled alpha flag, nothing's going to read it anymore. + if (rt) + { + GL_INS("RT alpha is now %s", rt->m_rt_alpha_scale ? "scaled" : "NOT scaled"); + rt->m_rt_alpha_scale = new_scale_rt_alpha; + m_conf.ps.rta_correction = rt->m_rt_alpha_scale; + } + if (features.framebuffer_fetch) { // Intel GPUs on Metal lock up if you try to use DSB and framebuffer fetch at once diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.h b/pcsx2/GS/Renderers/HW/GSRendererHW.h index 42b7329526..77b2f163c1 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.h +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.h @@ -87,7 +87,8 @@ private: 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, GSTextureCache::Target* rt); + void EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DATE_PRIMID, bool& DATE_BARRIER, GSTextureCache::Target* rt, + bool can_scale_rt_alpha, bool& new_rt_alpha_scale); void CleanupDraw(bool invalidate_temp_src); void EmulateTextureSampler(const GSTextureCache::Target* rt, const GSTextureCache::Target* ds,