From 6b54db9b7545db5775d42237e026916a61d58dbe Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Mon, 14 Mar 2022 16:04:07 +1000 Subject: [PATCH] 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. --- pcsx2/GS/GSState.cpp | 17 +++++++++++------ pcsx2/GS/Renderers/Common/GSVertexTrace.cpp | 16 +++++++++------- pcsx2/GS/Renderers/Common/GSVertexTrace.h | 4 ++-- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/pcsx2/GS/GSState.cpp b/pcsx2/GS/GSState.cpp index f51e21f8dc..b3d2dda0d2 100644 --- a/pcsx2/GS/GSState.cpp +++ b/pcsx2/GS/GSState.cpp @@ -29,6 +29,11 @@ static __fi bool IsAutoFlushEnabled() 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() : m_version(STATE_VERSION) , m_gsc(NULL) @@ -37,7 +42,7 @@ GSState::GSState() , m_q(1.0f) , m_scanmask_used(false) , tex_flushed(true) - , m_vt(this) + , m_vt(this, IsFirstProvokingVertex()) , m_regs(NULL) , m_crc(0) , m_options(0) @@ -252,11 +257,10 @@ void GSState::ResetHandlers() m_fpGIFPackedRegHandlers[GIF_REG_NOP] = &GSState::GIFPackedRegHandlerNOP; // 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()) - index_swap ? SetPrimHandlers() : SetPrimHandlers(); + IsFirstProvokingVertex() ? SetPrimHandlers() : SetPrimHandlers(); else - index_swap ? SetPrimHandlers() : SetPrimHandlers(); + IsFirstProvokingVertex() ? SetPrimHandlers() : SetPrimHandlers(); std::fill(std::begin(m_fpGIFRegHandlers), std::end(m_fpGIFRegHandlers), &GSState::GIFRegHandlerNull); @@ -3238,8 +3242,9 @@ bool GSState::TryAlphaTest(u32& fm, u32& zm) } else { - const int amin = GetAlphaMinMax().min; - const int amax = GetAlphaMinMax().max; + const GSVertexTrace::VertexAlpha& aminmax = GetAlphaMinMax(); + const int amin = aminmax.min; + const int amax = aminmax.max; const int aref = m_context->TEST.AREF; diff --git a/pcsx2/GS/Renderers/Common/GSVertexTrace.cpp b/pcsx2/GS/Renderers/Common/GSVertexTrace.cpp index 52fd7cb9b5..110a705e10 100644 --- a/pcsx2/GS/Renderers/Common/GSVertexTrace.cpp +++ b/pcsx2/GS/Renderers/Common/GSVertexTrace.cpp @@ -21,13 +21,15 @@ 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) { memset(&m_alpha, 0, sizeof(m_alpha)); #define InitUpdate3(P, IIP, TME, FST, COLOR) \ - m_fmm[COLOR][FST][TME][IIP][P] = &GSVertexTrace::FindMinMax; + m_fmm[COLOR][FST][TME][IIP][P] = \ + provoking_vertex_first ? &GSVertexTrace::FindMinMax : \ + &GSVertexTrace::FindMinMax; #define InitUpdate2(P, IIP, TME) \ InitUpdate3(P, IIP, TME, 0, 0) \ @@ -151,7 +153,7 @@ void GSVertexTrace::Update(const void* vertex, const u32* index, int v_count, in } } -template +template void GSVertexTrace::FindMinMax(const void* vertex, const u32* index, int count) { 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; 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 + 2]], v[index[i + 5]], true); + processVertices(v[index[i + 2]], v[index[i + 5]], !flat_swapped); } 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! // (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 diff --git a/pcsx2/GS/Renderers/Common/GSVertexTrace.h b/pcsx2/GS/Renderers/Common/GSVertexTrace.h index e026025424..688b02710d 100644 --- a/pcsx2/GS/Renderers/Common/GSVertexTrace.h +++ b/pcsx2/GS/Renderers/Common/GSVertexTrace.h @@ -48,7 +48,7 @@ protected: FindMinMaxPtr m_fmm[2][2][2][2][4]; - template + template void FindMinMax(const void* vertex, const u32* index, int count); public: @@ -73,7 +73,7 @@ public: GSVector2 m_lod; // x = min, y = max public: - GSVertexTrace(const GSState* state); + GSVertexTrace(const GSState* state, bool provoking_vertex_first); virtual ~GSVertexTrace() {} void Update(const void* vertex, const u32* index, int v_count, int i_count, GS_PRIM_CLASS primclass);