GS/HW: Pre check DATE requirement before updating rt alphas

This commit is contained in:
refractionpcsx2 2024-03-06 23:08:19 +00:00
parent 88192adfd0
commit 4d23410b99
1 changed files with 103 additions and 115 deletions

View File

@ -5047,6 +5047,34 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
const GSDevice::FeatureSupport features = g_gs_device->Features();
if (DATE)
{
// Should always be true, but sanity check...
if (rt)
{
const bool is_overlap_alpha = m_prim_overlap != PRIM_OVERLAP_NO && !(m_cached_ctx.FRAME.FBMSK & 0x80000000);
if (m_cached_ctx.TEST.DATM == 0)
{
// Some pixles are >= 1 so some fail, or some pixels get written but the written alpha matches or exceeds 1 (so overlap doesn't always pass).
DATE = rt->m_alpha_max >= 128 || (is_overlap_alpha && rt->m_alpha_min < 128 && (GetAlphaMinMax().max >= 128 || (m_context->FBA.FBA || IsCoverageAlpha())));
// All pixels fail.
if (DATE && rt->m_alpha_min >= 128)
return;
}
else
{
// Some pixles are < 1 so some fail, or some pixels get written but the written alpha goes below 1 (so overlap doesn't always pass).
DATE = rt->m_alpha_min < 128 || (is_overlap_alpha && rt->m_alpha_max >= 128 && (GetAlphaMinMax().min < 128 && !(m_context->FBA.FBA || IsCoverageAlpha())));
// All pixels fail.
if (DATE && rt->m_alpha_max < 128)
return;
}
}
}
// Blend
int blend_alpha_min = 0, blend_alpha_max = 255;
if (rt)
@ -5070,7 +5098,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
if ((m_cached_ctx.FRAME.FBMSK & alpha_mask) == 0)
{
if (rt->m_valid.rintersect(m_r).eq(rt->m_valid) && PrimitiveCoversWithoutGaps() && !(m_cached_ctx.TEST.DATE || m_cached_ctx.TEST.ATE || m_cached_ctx.TEST.ZTST != ZTST_ALWAYS))
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;
@ -5111,45 +5139,6 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
}
// DATE: selection of the algorithm. Must be done before blending because GL42 is not compatible with blending
if (DATE)
{
if (m_cached_ctx.TEST.DATM)
{
if (rt)
{
// Destination and incoming pixels are all 1 or higher, no need for DATE.
if ((rt->m_alpha_min >= 128 || (m_cached_ctx.FRAME.FBMSK & 0x80000000)) && blend_alpha_min >= 128)
{
DATE = false;
m_cached_ctx.TEST.DATE = false;
}
else if (blend_alpha_max < 128) // All dest pixels are less than 1, everything fails.
{
rt->m_alpha_max = blend_alpha_max;
rt->m_alpha_min = blend_alpha_min;
return;
}
}
}
else
{
if (rt)
{
// Destination and incoming pixels are all less than 1, no need for DATE.
if ((rt->m_alpha_max < 128 || (m_cached_ctx.FRAME.FBMSK & 0x80000000)) && blend_alpha_max < 128)
{
DATE = false;
m_cached_ctx.TEST.DATE = false;
}
else if (blend_alpha_min >= 128) // All dest pixels are 1 or higher, everything fails.
{
rt->m_alpha_max = blend_alpha_max;
rt->m_alpha_min = blend_alpha_min;
return;
}
}
}
if (DATE)
{
// It is way too complex to emulate texture shuffle with DATE, so use accurate path.
@ -5234,7 +5223,6 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
pxAssert(!(DATE_PRIMID && DATE_one));
pxAssert(!(DATE_PRIMID && DATE_BARRIER));
}
}
// Before emulateblending, dither will be used
m_conf.ps.dither = GSConfig.Dithering > 0 && m_conf.ps.dst_fmt == GSLocalMemory::PSM_FMT_16 && env.DTHE.DTHE;