diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 3cc39d4d7c..a81b17b28a 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -471,7 +471,7 @@ void GSRendererHW::ConvertSpriteTextureShuffle(u32& process_rg, u32& process_ba, GSVector4::storeh(&v[1].ST.S, st); } } - + m_r = fpr; m_vertex.head = m_vertex.tail = m_vertex.next = 2; m_index.tail = 2; return; @@ -1363,6 +1363,15 @@ bool GSRendererHW::IsRTWritten() (ALPHA.C == 0 && GetAlphaMinMax().max != 0))))); } +bool GSRendererHW::IsDepthAlwaysPassing() +{ + const u32 max_z = (0xFFFFFFFF >> (GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].fmt * 8)); + // Depth is always pass/fail (no read) and write are discarded. + return (!m_cached_ctx.TEST.ZTE || m_cached_ctx.TEST.ZTST <= ZTST_ALWAYS) || + // Depth test will always pass + (m_cached_ctx.TEST.ZTST == ZTST_GEQUAL && m_vt.m_eq.z && std::min(m_vertex.buff[0].XYZ.Z, max_z) == max_z); +} + bool GSRendererHW::IsUsingCsInBlend() { const GIFRegALPHA ALPHA = m_context->ALPHA; @@ -2047,13 +2056,8 @@ void GSRendererHW::Draw() // 2/ SuperMan really draws (0,0,0,0) color and a (0) 32-bits depth // 3/ 50cents really draws (0,0,0,128) color and a (0) 24 bits depth // Note: FF DoC has both buffer at same location but disable the depth test (write?) with ZTE = 0 - const u32 max_z = (0xFFFFFFFF >> (GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].fmt * 8)); bool no_rt = (!IsRTWritten() && !m_cached_ctx.TEST.DATE); - const bool all_depth_tests_pass = - // Depth is always pass/fail (no read) and write are discarded. - (!m_cached_ctx.TEST.ZTE || m_cached_ctx.TEST.ZTST <= ZTST_ALWAYS) || - // Depth test will always pass - (m_cached_ctx.TEST.ZTST == ZTST_GEQUAL && m_vt.m_eq.z && std::min(m_vertex.buff[0].XYZ.Z, max_z) == max_z); + const bool all_depth_tests_pass = IsDepthAlwaysPassing(); bool no_ds = (zm != 0 && all_depth_tests_pass) || // No color or Z being written. (no_rt && zm != 0); @@ -3588,6 +3592,8 @@ void GSRendererHW::EmulateTextureShuffleAndFbmask(GSTextureCache::Target* rt, GS m_cached_ctx.CLAMP.WMS = m_cached_ctx.CLAMP.WMS == CLAMP_REGION_CLAMP ? CLAMP_CLAMP : CLAMP_REPEAT; if (m_cached_ctx.CLAMP.WMT > CLAMP_CLAMP) m_cached_ctx.CLAMP.WMT = m_cached_ctx.CLAMP.WMT == CLAMP_REGION_CLAMP ? CLAMP_CLAMP : CLAMP_REPEAT; + + m_primitive_covers_without_gaps = rt->m_valid.rintersect(m_r).eq(rt->m_valid); } else { @@ -3836,8 +3842,12 @@ __ri bool GSRendererHW::EmulateChannelShuffle(GSTextureCache::Target* src, bool s[0].XYZ.Y = static_cast(m_context->XYOFFSET.OFY + 0); s[1].XYZ.Y = static_cast(m_context->XYOFFSET.OFY + 16384); + m_r = GSVector4i(0, 0, 1024, 1024); m_vertex.head = m_vertex.tail = m_vertex.next = 2; m_index.tail = 2; + + m_primitive_covers_without_gaps = true; + return true; } @@ -5218,7 +5228,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta 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 || (m_cached_ctx.TEST.ZTE && m_cached_ctx.TEST.ZTST != ZTST_ALWAYS)) || m_channel_shuffle); + const bool full_cover = rt->m_valid.rintersect(m_r).eq(rt->m_valid) && PrimitiveCoversWithoutGaps() && !(DATE || !always_passing_alpha || !IsDepthAlwaysPassing()); if ((fb_mask & alpha_mask) == 0) { @@ -5245,10 +5255,14 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta rt_new_alpha_min = std::min(s_alpha_min, rt_new_alpha_min); } - if (full_cover && (fb_mask & alpha_mask) == 0) - rt->m_alpha_range = s_alpha_max != s_alpha_min; - else - rt->m_alpha_range |= (s_alpha_max & ~fb_mask) != (s_alpha_min & ~fb_mask); + + if ((fb_mask & alpha_mask) != alpha_mask) + { + if (full_cover && (fb_mask & alpha_mask) == 0) + rt->m_alpha_range = s_alpha_max != s_alpha_min; + else + rt->m_alpha_range |= (s_alpha_max & ~fb_mask) != (s_alpha_min & ~fb_mask); + } } else if ((m_texture_shuffle && m_conf.colormask.wa)) { @@ -5497,7 +5511,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta { 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 || (m_cached_ctx.TEST.ZTE && m_cached_ctx.TEST.ZTST != ZTST_ALWAYS)); + const bool full_cover = rt->m_valid.rintersect(m_r).eq(rt->m_valid) && PrimitiveCoversWithoutGaps() && !(DATE || !always_passing_alpha || !IsDepthAlwaysPassing()); if (!full_cover) { diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.h b/pcsx2/GS/Renderers/HW/GSRendererHW.h index dc5464f4b8..42b7329526 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.h +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.h @@ -119,6 +119,7 @@ private: void FinishSplitClear(); bool IsRTWritten(); + bool IsDepthAlwaysPassing(); bool IsUsingCsInBlend(); bool IsUsingAsInBlend();