GS/HW: Instead of adjusting blend min/max, adjust GetAlphaMinMax.

Might help in blending cases.
This commit is contained in:
lightningterror 2024-03-11 02:52:53 +00:00 committed by refractionpcsx2
parent 74df63ff94
commit b4992856f7
4 changed files with 49 additions and 38 deletions

View File

@ -3962,6 +3962,41 @@ void GSState::CalcAlphaMinMax(const int tex_alpha_min, const int tex_alpha_max)
m_vt.m_alpha.valid = true;
}
void GSState::CorrectATEAlphaMinMax(const u32 atst, const int aref)
{
const GSVertexTrace::VertexAlpha& aminmax = GetAlphaMinMax();
int amin = aminmax.min;
int amax = aminmax.max;
switch (atst)
{
case ATST_LESS:
amin = std::min(amin, std::max(aref - 1, amin));
amax = std::min(amax, std::max(aref - 1, amin));
break;
case ATST_LEQUAL:
amin = std::min(amin, std::max(aref, amin));
amax = std::min(amax, std::max(aref, amin));
break;
case ATST_EQUAL:
amax = aref;
amin = aref;
break;
case ATST_GEQUAL:
amax = std::max(amax, std::min(aref, amax));
amin = std::max(amin, std::min(aref, amax));
break;
case ATST_GREATER:
amax = std::max(amax, std::min(aref + 1, amax));
amin = std::max(amin, std::min(aref + 1, amax));
break;
default:
break;
}
m_vt.m_alpha.min = amin;
m_vt.m_alpha.max = amax;
}
bool GSState::TryAlphaTest(u32& fm, u32& zm)
{
// Shortcut for the easy case

View File

@ -187,6 +187,7 @@ protected:
bool IsMipMapActive();
bool IsCoverageAlpha();
void CalcAlphaMinMax(const int tex_min, const int tex_max);
void CorrectATEAlphaMinMax(const u32 atst, const int aref);
public:
struct GSUploadQueue

View File

@ -682,6 +682,8 @@ bool GSHwHack::GSC_PolyphonyDigitalGames(GSRendererHW& r, int& skip)
{
GL_PUSH("GSC_PolyphonyDigitalGames(): HLE Gran Turismo RGB channel shuffle");
src->m_alpha_max = 255;
src->m_alpha_min = 0;
GSHWDrawConfig& config = r.BeginHLEHardwareDraw(
src->GetTexture(), nullptr, src->GetScale(), src->GetTexture(), src->GetScale(), src->GetUnscaledRect());
config.pal = palette->GetPaletteGSTexture();

View File

@ -5060,53 +5060,22 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
}
}
const int fail_type = m_cached_ctx.TEST.GetAFAIL(m_cached_ctx.FRAME.PSM);
const int aref = static_cast<int>(m_cached_ctx.TEST.AREF);
if (m_cached_ctx.TEST.ATE && ((fail_type != AFAIL_FB_ONLY && fail_type != AFAIL_RGB_ONLY) || !PRIM->ABE || !IsUsingAsInBlend()))
CorrectATEAlphaMinMax(m_cached_ctx.TEST.ATST, aref);
// Blend
int blend_alpha_min = 0, blend_alpha_max = 255;
if (rt)
{
blend_alpha_min = rt->m_alpha_min;
blend_alpha_max = rt->m_alpha_max;
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_draw_env->CTXT[m_draw_env->PRIM.CTXT].FBA.FBA * 128;
int s_alpha_max = GetAlphaMinMax().max;
int s_alpha_min = GetAlphaMinMax().min;
{
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;
}
}
}
s_alpha_max |= fba_value;
s_alpha_min |= fba_value;
if (is_24_bit)
{
@ -5117,9 +5086,13 @@ __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 s_alpha_max = GetAlphaMinMax().max | fba_value;
const int s_alpha_min = GetAlphaMinMax().min | fba_value;
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)))
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);
if (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)))
{
rt->m_alpha_max = s_alpha_max;
rt->m_alpha_min = s_alpha_min;