GS/VertexTrace: Fix min/max when last provoking vertex unsupported

This was causing incorrect min/max alpha values due to the index swap,
which caused the sides of text boxes in KH to disappear (because the
alpha test optimized to always failing).

Closes #5639.
This commit is contained in:
Connor McLaughlin 2022-03-14 16:04:07 +10:00 committed by refractionpcsx2
parent 3bab470db6
commit 6b54db9b75
3 changed files with 22 additions and 15 deletions

View File

@ -29,6 +29,11 @@ static __fi bool IsAutoFlushEnabled()
return (GSConfig.Renderer == GSRendererType::SW) ? GSConfig.AutoFlushSW : GSConfig.UserHacks_AutoFlush; return (GSConfig.Renderer == GSRendererType::SW) ? GSConfig.AutoFlushSW : GSConfig.UserHacks_AutoFlush;
} }
static __fi bool IsFirstProvokingVertex()
{
return (GSConfig.Renderer != GSRendererType::SW && !g_gs_device->Features().provoking_vertex_last);
}
GSState::GSState() GSState::GSState()
: m_version(STATE_VERSION) : m_version(STATE_VERSION)
, m_gsc(NULL) , m_gsc(NULL)
@ -37,7 +42,7 @@ GSState::GSState()
, m_q(1.0f) , m_q(1.0f)
, m_scanmask_used(false) , m_scanmask_used(false)
, tex_flushed(true) , tex_flushed(true)
, m_vt(this) , m_vt(this, IsFirstProvokingVertex())
, m_regs(NULL) , m_regs(NULL)
, m_crc(0) , m_crc(0)
, m_options(0) , m_options(0)
@ -252,11 +257,10 @@ void GSState::ResetHandlers()
m_fpGIFPackedRegHandlers[GIF_REG_NOP] = &GSState::GIFPackedRegHandlerNOP; m_fpGIFPackedRegHandlers[GIF_REG_NOP] = &GSState::GIFPackedRegHandlerNOP;
// swap first/last indices when the provoking vertex is the first (D3D/Vulkan) // swap first/last indices when the provoking vertex is the first (D3D/Vulkan)
const bool index_swap = GSConfig.UseHardwareRenderer() && !g_gs_device->Features().provoking_vertex_last;
if (IsAutoFlushEnabled()) if (IsAutoFlushEnabled())
index_swap ? SetPrimHandlers<true, true>() : SetPrimHandlers<true, false>(); IsFirstProvokingVertex() ? SetPrimHandlers<true, true>() : SetPrimHandlers<true, false>();
else else
index_swap ? SetPrimHandlers<false, true>() : SetPrimHandlers<false, false>(); IsFirstProvokingVertex() ? SetPrimHandlers<false, true>() : SetPrimHandlers<false, false>();
std::fill(std::begin(m_fpGIFRegHandlers), std::end(m_fpGIFRegHandlers), &GSState::GIFRegHandlerNull); std::fill(std::begin(m_fpGIFRegHandlers), std::end(m_fpGIFRegHandlers), &GSState::GIFRegHandlerNull);
@ -3238,8 +3242,9 @@ bool GSState::TryAlphaTest(u32& fm, u32& zm)
} }
else else
{ {
const int amin = GetAlphaMinMax().min; const GSVertexTrace::VertexAlpha& aminmax = GetAlphaMinMax();
const int amax = GetAlphaMinMax().max; const int amin = aminmax.min;
const int amax = aminmax.max;
const int aref = m_context->TEST.AREF; const int aref = m_context->TEST.AREF;

View File

@ -21,13 +21,15 @@
CONSTINIT const GSVector4 GSVertexTrace::s_minmax = GSVector4::cxpr(FLT_MAX, -FLT_MAX, 0.f, 0.f); CONSTINIT const GSVector4 GSVertexTrace::s_minmax = GSVector4::cxpr(FLT_MAX, -FLT_MAX, 0.f, 0.f);
GSVertexTrace::GSVertexTrace(const GSState* state) GSVertexTrace::GSVertexTrace(const GSState* state, bool provoking_vertex_first)
: m_accurate_stq(false), m_state(state), m_primclass(GS_INVALID_CLASS) : m_accurate_stq(false), m_state(state), m_primclass(GS_INVALID_CLASS)
{ {
memset(&m_alpha, 0, sizeof(m_alpha)); memset(&m_alpha, 0, sizeof(m_alpha));
#define InitUpdate3(P, IIP, TME, FST, COLOR) \ #define InitUpdate3(P, IIP, TME, FST, COLOR) \
m_fmm[COLOR][FST][TME][IIP][P] = &GSVertexTrace::FindMinMax<P, IIP, TME, FST, COLOR>; m_fmm[COLOR][FST][TME][IIP][P] = \
provoking_vertex_first ? &GSVertexTrace::FindMinMax<P, IIP, TME, FST, COLOR, true> : \
&GSVertexTrace::FindMinMax<P, IIP, TME, FST, COLOR, false>;
#define InitUpdate2(P, IIP, TME) \ #define InitUpdate2(P, IIP, TME) \
InitUpdate3(P, IIP, TME, 0, 0) \ InitUpdate3(P, IIP, TME, 0, 0) \
@ -151,7 +153,7 @@ void GSVertexTrace::Update(const void* vertex, const u32* index, int v_count, in
} }
} }
template <GS_PRIM_CLASS primclass, u32 iip, u32 tme, u32 fst, u32 color> template <GS_PRIM_CLASS primclass, u32 iip, u32 tme, u32 fst, u32 color, bool flat_swapped>
void GSVertexTrace::FindMinMax(const void* vertex, const u32* index, int count) void GSVertexTrace::FindMinMax(const void* vertex, const u32* index, int count)
{ {
const GSDrawingContext* context = m_state->m_context; const GSDrawingContext* context = m_state->m_context;
@ -283,16 +285,16 @@ void GSVertexTrace::FindMinMax(const void* vertex, const u32* index, int count)
int i = 0; int i = 0;
for (; i < (count - 3); i += 6) for (; i < (count - 3); i += 6)
{ {
processVertices(v[index[i + 0]], v[index[i + 3]], false); processVertices(v[index[i + 0]], v[index[i + 3]], flat_swapped);
processVertices(v[index[i + 1]], v[index[i + 4]], false); processVertices(v[index[i + 1]], v[index[i + 4]], false);
processVertices(v[index[i + 2]], v[index[i + 5]], true); processVertices(v[index[i + 2]], v[index[i + 5]], !flat_swapped);
} }
if (count & 1) if (count & 1)
{ {
processVertices(v[index[i + 0]], v[index[i + 1]], false); processVertices(v[index[i + 0]], v[index[i + 1]], flat_swapped);
// Compiler optimizations go! // Compiler optimizations go!
// (And if they don't, it's only one vertex out of many) // (And if they don't, it's only one vertex out of many)
processVertices(v[index[i + 2]], v[index[i + 2]], true); processVertices(v[index[i + 2]], v[index[i + 2]], !flat_swapped);
} }
} }
else else

View File

@ -48,7 +48,7 @@ protected:
FindMinMaxPtr m_fmm[2][2][2][2][4]; FindMinMaxPtr m_fmm[2][2][2][2][4];
template <GS_PRIM_CLASS primclass, u32 iip, u32 tme, u32 fst, u32 color> template <GS_PRIM_CLASS primclass, u32 iip, u32 tme, u32 fst, u32 color, bool provoking_vertex_first>
void FindMinMax(const void* vertex, const u32* index, int count); void FindMinMax(const void* vertex, const u32* index, int count);
public: public:
@ -73,7 +73,7 @@ public:
GSVector2 m_lod; // x = min, y = max GSVector2 m_lod; // x = min, y = max
public: public:
GSVertexTrace(const GSState* state); GSVertexTrace(const GSState* state, bool provoking_vertex_first);
virtual ~GSVertexTrace() {} virtual ~GSVertexTrace() {}
void Update(const void* vertex, const u32* index, int v_count, int i_count, GS_PRIM_CLASS primclass); void Update(const void* vertex, const u32* index, int v_count, int i_count, GS_PRIM_CLASS primclass);