Skip to content

Commit

Permalink
GS/HW: Calculate blend/rt alpha min/max based on alpha test.
Browse files Browse the repository at this point in the history
  • Loading branch information
lightningterror committed Mar 9, 2024
1 parent 67ca285 commit 0607040
Showing 1 changed file with 41 additions and 8 deletions.
49 changes: 41 additions & 8 deletions pcsx2/GS/Renderers/HW/GSRendererHW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5084,6 +5084,41 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta

const bool is_24_bit = (GSLocalMemory::m_psm[rt->m_TEX0.PSM].trbpp == 24);
const u32 alpha_mask = GSLocalMemory::m_psm[rt->m_TEX0.PSM].fmsk & 0xFF000000;
const int fba_value = m_prev_env.CTXT[m_prev_env.PRIM.CTXT].FBA.FBA * 128;
int s_alpha_max = GetAlphaMinMax().max | fba_value;
int s_alpha_min = GetAlphaMinMax().min | fba_value;
{
const int fail_type = m_cached_ctx.TEST.GetAFAIL(m_cached_ctx.FRAME.PSM);
if (m_cached_ctx.TEST.ATE && ((fail_type != AFAIL_FB_ONLY) || ((fail_type == AFAIL_RGB_ONLY) && (m_conf.ps.dst_fmt != GSLocalMemory::PSM_FMT_32))))
{
const int aref = static_cast<int>(m_cached_ctx.TEST.AREF);
switch (m_cached_ctx.TEST.ATST)
{
case ATST_LESS:
s_alpha_max = std::min(s_alpha_max, aref - 1);
s_alpha_min = std::min(s_alpha_min, s_alpha_max);
break;
case ATST_LEQUAL:
s_alpha_max = std::min(s_alpha_max, aref);
s_alpha_min = std::min(s_alpha_min, s_alpha_max);
break;
case ATST_EQUAL:
s_alpha_max = aref;
s_alpha_min = aref;
break;
case ATST_GEQUAL:
s_alpha_max = std::max(s_alpha_max, aref);
s_alpha_min = std::max(s_alpha_min, aref);
break;
case ATST_GREATER:
s_alpha_max = std::max(s_alpha_max, aref + 1);
s_alpha_min = std::max(s_alpha_min, aref + 1);
break;
default:
break;
}
}
}

if (is_24_bit)
{
Expand All @@ -5094,25 +5129,23 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta

if (GSUtil::GetChannelMask(m_cached_ctx.FRAME.PSM) & 0x8 && !m_channel_shuffle && !m_texture_shuffle)
{
const int fba_value = m_prev_env.CTXT[m_prev_env.PRIM.CTXT].FBA.FBA * 128;

if ((m_cached_ctx.FRAME.FBMSK & alpha_mask) == 0)
{
if (rt->m_valid.rintersect(m_r).eq(rt->m_valid) && PrimitiveCoversWithoutGaps() && !(DATE || m_cached_ctx.TEST.ATE || (m_cached_ctx.TEST.ZTE && m_cached_ctx.TEST.ZTST != ZTST_ALWAYS)))
{
rt->m_alpha_max = GetAlphaMinMax().max | fba_value;
rt->m_alpha_min = GetAlphaMinMax().min | fba_value;
rt->m_alpha_max = s_alpha_max;
rt->m_alpha_min = s_alpha_min;
}
else
{
rt->m_alpha_max = std::max(GetAlphaMinMax().max | fba_value, rt->m_alpha_max);
rt->m_alpha_min = std::min(GetAlphaMinMax().min | fba_value, rt->m_alpha_min);
rt->m_alpha_max = std::max(s_alpha_max, rt->m_alpha_max);
rt->m_alpha_min = std::min(s_alpha_min, rt->m_alpha_min);
}
}
else if ((m_cached_ctx.FRAME.FBMSK & alpha_mask) != alpha_mask) // We can't be sure of the alpha if it's partially masked.
{
rt->m_alpha_max |= std::max(GetAlphaMinMax().max | fba_value, rt->m_alpha_max);
rt->m_alpha_min = std::min(GetAlphaMinMax().min | fba_value, rt->m_alpha_min);
rt->m_alpha_max |= std::max(s_alpha_max, rt->m_alpha_max);
rt->m_alpha_min = std::min(s_alpha_min, rt->m_alpha_min);
}
}
else if ((m_texture_shuffle && m_conf.colormask.wa) || (m_channel_shuffle && (m_cached_ctx.FRAME.FBMSK & alpha_mask) != alpha_mask))
Expand Down

0 comments on commit 0607040

Please sign in to comment.