diff --git a/pcsx2/GS/GSState.cpp b/pcsx2/GS/GSState.cpp index f0dbee2931..7429127dde 100644 --- a/pcsx2/GS/GSState.cpp +++ b/pcsx2/GS/GSState.cpp @@ -27,11 +27,6 @@ static __fi bool IsAutoFlushEnabled() return GSIsHardwareRenderer() ? (GSConfig.UserHacks_AutoFlush != GSHWAutoFlushLevel::Disabled) : GSConfig.AutoFlushSW; } -static __fi bool IsFirstProvokingVertex() -{ - return (GSIsHardwareRenderer() && !g_gs_device->Features().provoking_vertex_last); -} - constexpr int GSState::GetSaveStateSize(int version) { int size = 0; @@ -99,7 +94,7 @@ constexpr int GSState::GetSaveStateSize(int version) } GSState::GSState() - : m_vt(this, IsFirstProvokingVertex()) + : m_vt(this) { // m_nativeres seems to be a hack. Unfortunately it impacts draw call number which make debug painful in the replayer. // Let's keep it disabled to ease debug. @@ -206,29 +201,29 @@ void GSState::Reset(bool hardware_reset) memcpy(&m_prev_env, &m_env, sizeof(m_prev_env)); } -template +template void GSState::SetPrimHandlers() { -#define SetHandlerXYZ(P, auto_flush, index_swap) \ - m_fpGIFPackedRegHandlerXYZ[P][0] = &GSState::GIFPackedRegHandlerXYZF2; \ - m_fpGIFPackedRegHandlerXYZ[P][1] = &GSState::GIFPackedRegHandlerXYZF2; \ - m_fpGIFPackedRegHandlerXYZ[P][2] = &GSState::GIFPackedRegHandlerXYZ2; \ - m_fpGIFPackedRegHandlerXYZ[P][3] = &GSState::GIFPackedRegHandlerXYZ2; \ - m_fpGIFRegHandlerXYZ[P][0] = &GSState::GIFRegHandlerXYZF2; \ - m_fpGIFRegHandlerXYZ[P][1] = &GSState::GIFRegHandlerXYZF2; \ - m_fpGIFRegHandlerXYZ[P][2] = &GSState::GIFRegHandlerXYZ2; \ - m_fpGIFRegHandlerXYZ[P][3] = &GSState::GIFRegHandlerXYZ2; \ - m_fpGIFPackedRegHandlerSTQRGBAXYZF2[P] = &GSState::GIFPackedRegHandlerSTQRGBAXYZF2; \ - m_fpGIFPackedRegHandlerSTQRGBAXYZ2[P] = &GSState::GIFPackedRegHandlerSTQRGBAXYZ2; +#define SetHandlerXYZ(P, auto_flush) \ + m_fpGIFPackedRegHandlerXYZ[P][0] = &GSState::GIFPackedRegHandlerXYZF2; \ + m_fpGIFPackedRegHandlerXYZ[P][1] = &GSState::GIFPackedRegHandlerXYZF2; \ + m_fpGIFPackedRegHandlerXYZ[P][2] = &GSState::GIFPackedRegHandlerXYZ2; \ + m_fpGIFPackedRegHandlerXYZ[P][3] = &GSState::GIFPackedRegHandlerXYZ2; \ + m_fpGIFRegHandlerXYZ[P][0] = &GSState::GIFRegHandlerXYZF2; \ + m_fpGIFRegHandlerXYZ[P][1] = &GSState::GIFRegHandlerXYZF2; \ + m_fpGIFRegHandlerXYZ[P][2] = &GSState::GIFRegHandlerXYZ2; \ + m_fpGIFRegHandlerXYZ[P][3] = &GSState::GIFRegHandlerXYZ2; \ + m_fpGIFPackedRegHandlerSTQRGBAXYZF2[P] = &GSState::GIFPackedRegHandlerSTQRGBAXYZF2; \ + m_fpGIFPackedRegHandlerSTQRGBAXYZ2[P] = &GSState::GIFPackedRegHandlerSTQRGBAXYZ2; - SetHandlerXYZ(GS_POINTLIST, true, false); - SetHandlerXYZ(GS_LINELIST, auto_flush, index_swap); - SetHandlerXYZ(GS_LINESTRIP, auto_flush, index_swap); - SetHandlerXYZ(GS_TRIANGLELIST, auto_flush, index_swap); - SetHandlerXYZ(GS_TRIANGLESTRIP, auto_flush, index_swap); - SetHandlerXYZ(GS_TRIANGLEFAN, auto_flush, index_swap); - SetHandlerXYZ(GS_SPRITE, auto_flush, false); - SetHandlerXYZ(GS_INVALID, auto_flush, false); + SetHandlerXYZ(GS_POINTLIST, true); + SetHandlerXYZ(GS_LINELIST, auto_flush); + SetHandlerXYZ(GS_LINESTRIP, auto_flush); + SetHandlerXYZ(GS_TRIANGLELIST, auto_flush); + SetHandlerXYZ(GS_TRIANGLESTRIP, auto_flush); + SetHandlerXYZ(GS_TRIANGLEFAN, auto_flush); + SetHandlerXYZ(GS_SPRITE, auto_flush); + SetHandlerXYZ(GS_INVALID, auto_flush); #undef SetHandlerXYZ } @@ -249,11 +244,10 @@ void GSState::ResetHandlers() m_fpGIFPackedRegHandlers[GIF_REG_A_D] = &GSState::GIFPackedRegHandlerA_D; m_fpGIFPackedRegHandlers[GIF_REG_NOP] = &GSState::GIFPackedRegHandlerNOP; - // swap first/last indices when the provoking vertex is the first (D3D/Vulkan) if (IsAutoFlushEnabled()) - IsFirstProvokingVertex() ? SetPrimHandlers() : SetPrimHandlers(); + SetPrimHandlers(); else - IsFirstProvokingVertex() ? SetPrimHandlers() : SetPrimHandlers(); + SetPrimHandlers(); std::fill(std::begin(m_fpGIFRegHandlers), std::end(m_fpGIFRegHandlers), &GSState::GIFRegHandlerNull); @@ -606,7 +600,7 @@ void GSState::GIFPackedRegHandlerUV_Hack(const GIFPackedReg* RESTRICT r) m_isPackedUV_HackFlag = true; } -template +template void GSState::GIFPackedRegHandlerXYZF2(const GIFPackedReg* RESTRICT r) { const bool skip = adc || r->XYZF2.Skip(); @@ -622,10 +616,10 @@ void GSState::GIFPackedRegHandlerXYZF2(const GIFPackedReg* RESTRICT r) m_v.m[1] = xy.upl32(zf); - VertexKick(skip); + VertexKick(skip); } -template +template void GSState::GIFPackedRegHandlerXYZ2(const GIFPackedReg* RESTRICT r) { const bool skip = adc || r->XYZ2.Skip(); @@ -639,7 +633,7 @@ void GSState::GIFPackedRegHandlerXYZ2(const GIFPackedReg* RESTRICT r) m_v.m[1] = xyz.upl64(GSVector4i::loadl(&m_v.UV)); - VertexKick(skip); + VertexKick(skip); } void GSState::GIFPackedRegHandlerFOG(const GIFPackedReg* RESTRICT r) @@ -656,7 +650,7 @@ void GSState::GIFPackedRegHandlerNOP(const GIFPackedReg* RESTRICT r) { } -template +template void GSState::GIFPackedRegHandlerSTQRGBAXYZF2(const GIFPackedReg* RESTRICT r, u32 size) { pxAssert(size > 0 && size % 3 == 0); @@ -682,7 +676,7 @@ void GSState::GIFPackedRegHandlerSTQRGBAXYZF2(const GIFPackedReg* RESTRICT r, u3 m_v.m[1] = xy.upl32(zf); // TODO: only store the last one - VertexKick(r[2].XYZF2.Skip()); + VertexKick(r[2].XYZF2.Skip()); r += 3; } @@ -690,7 +684,7 @@ void GSState::GIFPackedRegHandlerSTQRGBAXYZF2(const GIFPackedReg* RESTRICT r, u3 m_q = r[-3].STQ.Q; // remember the last one, STQ outputs this to the temp Q each time } -template +template void GSState::GIFPackedRegHandlerSTQRGBAXYZ2(const GIFPackedReg* RESTRICT r, u32 size) { pxAssert(size > 0 && size % 3 == 0); @@ -715,7 +709,7 @@ void GSState::GIFPackedRegHandlerSTQRGBAXYZ2(const GIFPackedReg* RESTRICT r, u32 m_v.m[1] = xyz.upl64(GSVector4i::loadl(&m_v.UV)); // TODO: only store the last one - VertexKick(r[2].XYZ2.Skip()); + VertexKick(r[2].XYZ2.Skip()); r += 3; } @@ -749,7 +743,7 @@ __forceinline void GSState::ApplyPRIM(u32 prim) UpdateVertexKick(); - pxAssert(m_index.tail == 0 || !g_gs_device->Features().provoking_vertex_last || m_index.buff[m_index.tail - 1] + 1 == m_vertex.next); + pxAssert(m_index.tail == 0 || m_index.buff[m_index.tail - 1] + 1 == m_vertex.next); if (m_index.tail == 0) m_vertex.next = 0; @@ -800,7 +794,7 @@ void GSState::GIFRegHandlerUV_Hack(const GIFReg* RESTRICT r) m_isPackedUV_HackFlag = false; } -template +template void GSState::GIFRegHandlerXYZF2(const GIFReg* RESTRICT r) { if (!adc || GSUtil::GetPrimClass(m_prev_env.PRIM.PRIM) != GSUtil::GetPrimClass(m_env.PRIM.PRIM) || (m_dirty_gs_regs & (1 << DIRTY_REG_XYOFFSET))) @@ -812,10 +806,10 @@ void GSState::GIFRegHandlerXYZF2(const GIFReg* RESTRICT r) m_v.m[1] = xyz.upl64(uvf); - VertexKick(adc); + VertexKick(adc); } -template +template void GSState::GIFRegHandlerXYZ2(const GIFReg* RESTRICT r) { if (!adc || GSUtil::GetPrimClass(m_prev_env.PRIM.PRIM) != GSUtil::GetPrimClass(m_env.PRIM.PRIM) || (m_dirty_gs_regs & (1 << DIRTY_REG_XYOFFSET))) @@ -823,7 +817,7 @@ void GSState::GIFRegHandlerXYZ2(const GIFReg* RESTRICT r) m_v.m[1] = GSVector4i::load(&r->XYZ, &m_v.UV); - VertexKick(adc); + VertexKick(adc); } template @@ -3381,7 +3375,7 @@ __forceinline void GSState::CheckCLUTValidity(u32 prim) } } -template +template __forceinline void GSState::HandleAutoFlush() { // Kind of a cheat, making the assumption that 2 consecutive fan/strip triangles won't overlap each other (*should* be safe) @@ -3477,9 +3471,8 @@ __forceinline void GSState::HandleAutoFlush() if (tex_rect.y == tex_rect.w) tex_rect += GSVector4i::cxpr(0, 0, 0, 1); - const bool swap_index = index_swap && GSUtil::GetPrimClass(m_prev_env.PRIM.PRIM) != GS_SPRITE_CLASS; // Get the last texture position from the last draw. - const GSVertex* v = &m_vertex.buff[m_index.buff[m_index.tail - (swap_index ? n : 1)]]; + const GSVertex* v = &m_vertex.buff[m_index.buff[m_index.tail - 1]]; if (PRIM->FST) { @@ -3657,7 +3650,7 @@ __forceinline void GSState::HandleAutoFlush() } } -template +template __forceinline void GSState::VertexKick(u32 skip) { constexpr u32 n = NumIndicesForPrim(prim); @@ -3673,7 +3666,7 @@ __forceinline void GSState::VertexKick(u32 skip) if (auto_flush && skip == 0 && m_index.tail > 0 && ((m_vertex.tail + 1) - m_vertex.head) >= n) { - HandleAutoFlush(); + HandleAutoFlush(); } u32 head = m_vertex.head; @@ -3835,8 +3828,8 @@ __forceinline void GSState::VertexKick(u32 skip) m_index.tail += 1; break; case GS_LINELIST: - buff[0] = static_cast(head + (index_swap ? 1 : 0)); - buff[1] = static_cast(head + (index_swap ? 0 : 1)); + buff[0] = static_cast(head + 0); + buff[1] = static_cast(head + 1); m_vertex.head = head + 2; m_vertex.next = head + 2; m_index.tail += 2; @@ -3849,16 +3842,16 @@ __forceinline void GSState::VertexKick(u32 skip) head = next; m_vertex.tail = next + 2; } - buff[0] = static_cast(head + (index_swap ? 1 : 0)); - buff[1] = static_cast(head + (index_swap ? 0 : 1)); + buff[0] = static_cast(head + 0); + buff[1] = static_cast(head + 1); m_vertex.head = head + 1; m_vertex.next = head + 2; m_index.tail += 2; break; case GS_TRIANGLELIST: - buff[0] = static_cast(head + (index_swap ? 2 : 0)); + buff[0] = static_cast(head + 0); buff[1] = static_cast(head + 1); - buff[2] = static_cast(head + (index_swap ? 0 : 2)); + buff[2] = static_cast(head + 2); m_vertex.head = head + 3; m_vertex.next = head + 3; m_index.tail += 3; @@ -3872,18 +3865,18 @@ __forceinline void GSState::VertexKick(u32 skip) head = next; m_vertex.tail = next + 3; } - buff[0] = static_cast(head + (index_swap ? 2 : 0)); + buff[0] = static_cast(head + 0); buff[1] = static_cast(head + 1); - buff[2] = static_cast(head + (index_swap ? 0 : 2)); + buff[2] = static_cast(head + 2); m_vertex.head = head + 1; m_vertex.next = head + 3; m_index.tail += 3; break; case GS_TRIANGLEFAN: // TODO: remove gaps, next == head && head < tail - 3 || next > head && next < tail - 2 (very rare) - buff[0] = static_cast(index_swap ? (tail - 1) : (head + 0)); + buff[0] = static_cast(head + 0); buff[1] = static_cast(tail - 2); - buff[2] = static_cast(index_swap ? (head + 0) : (tail - 1)); + buff[2] = static_cast(tail - 1); m_vertex.next = tail; m_index.tail += 3; break; diff --git a/pcsx2/GS/GSState.h b/pcsx2/GS/GSState.h index 69184b46da..2e60282c39 100644 --- a/pcsx2/GS/GSState.h +++ b/pcsx2/GS/GSState.h @@ -38,8 +38,8 @@ private: void GIFPackedRegHandlerSTQ(const GIFPackedReg* RESTRICT r); void GIFPackedRegHandlerUV(const GIFPackedReg* RESTRICT r); void GIFPackedRegHandlerUV_Hack(const GIFPackedReg* RESTRICT r); - template void GIFPackedRegHandlerXYZF2(const GIFPackedReg* RESTRICT r); - template void GIFPackedRegHandlerXYZ2(const GIFPackedReg* RESTRICT r); + template void GIFPackedRegHandlerXYZF2(const GIFPackedReg* RESTRICT r); + template void GIFPackedRegHandlerXYZ2(const GIFPackedReg* RESTRICT r); void GIFPackedRegHandlerFOG(const GIFPackedReg* RESTRICT r); void GIFPackedRegHandlerA_D(const GIFPackedReg* RESTRICT r); void GIFPackedRegHandlerNOP(const GIFPackedReg* RESTRICT r); @@ -55,8 +55,8 @@ private: GIFPackedRegHandlerC m_fpGIFPackedRegHandlerSTQRGBAXYZF2[8] = {}; GIFPackedRegHandlerC m_fpGIFPackedRegHandlerSTQRGBAXYZ2[8] = {}; - template void GIFPackedRegHandlerSTQRGBAXYZF2(const GIFPackedReg* RESTRICT r, u32 size); - template void GIFPackedRegHandlerSTQRGBAXYZ2(const GIFPackedReg* RESTRICT r, u32 size); + template void GIFPackedRegHandlerSTQRGBAXYZF2(const GIFPackedReg* RESTRICT r, u32 size); + template void GIFPackedRegHandlerSTQRGBAXYZ2(const GIFPackedReg* RESTRICT r, u32 size); void GIFPackedRegHandlerNOP(const GIFPackedReg* RESTRICT r, u32 size); template void ApplyTEX0(GIFRegTEX0& TEX0); @@ -68,8 +68,8 @@ private: void GIFRegHandlerST(const GIFReg* RESTRICT r); void GIFRegHandlerUV(const GIFReg* RESTRICT r); void GIFRegHandlerUV_Hack(const GIFReg* RESTRICT r); - template void GIFRegHandlerXYZF2(const GIFReg* RESTRICT r); - template void GIFRegHandlerXYZ2(const GIFReg* RESTRICT r); + template void GIFRegHandlerXYZF2(const GIFReg* RESTRICT r); + template void GIFRegHandlerXYZ2(const GIFReg* RESTRICT r); template void GIFRegHandlerTEX0(const GIFReg* RESTRICT r); template void GIFRegHandlerCLAMP(const GIFReg* RESTRICT r); void GIFRegHandlerFOG(const GIFReg* RESTRICT r); @@ -102,8 +102,7 @@ private: void GIFRegHandlerTRXDIR(const GIFReg* RESTRICT r); void GIFRegHandlerHWREG(const GIFReg* RESTRICT r); - template - void SetPrimHandlers(); + template void SetPrimHandlers(); struct GSTransferBuffer { @@ -171,12 +170,10 @@ protected: void GrowVertexBuffer(); bool IsAutoFlushDraw(u32 prim); - template - void HandleAutoFlush(); + template void HandleAutoFlush(); void CheckCLUTValidity(u32 prim); - template - void VertexKick(u32 skip); + template void VertexKick(u32 skip); // following functions need m_vt to be initialized diff --git a/pcsx2/GS/Renderers/Common/GSVertexTrace.cpp b/pcsx2/GS/Renderers/Common/GSVertexTrace.cpp index 469ec14207..00b873a1c3 100644 --- a/pcsx2/GS/Renderers/Common/GSVertexTrace.cpp +++ b/pcsx2/GS/Renderers/Common/GSVertexTrace.cpp @@ -7,10 +7,10 @@ #include "common/Console.h" -GSVertexTrace::GSVertexTrace(const GSState* state, bool provoking_vertex_first) +GSVertexTrace::GSVertexTrace(const GSState* state) : m_state(state) { - MULTI_ISA_SELECT(GSVertexTracePopulateFunctions)(*this, provoking_vertex_first); + MULTI_ISA_SELECT(GSVertexTracePopulateFunctions)(*this); } void GSVertexTrace::Update(const void* vertex, const u16* index, int v_count, int i_count, GS_PRIM_CLASS primclass) diff --git a/pcsx2/GS/Renderers/Common/GSVertexTrace.h b/pcsx2/GS/Renderers/Common/GSVertexTrace.h index d50c9b0488..b44f5fee6d 100644 --- a/pcsx2/GS/Renderers/Common/GSVertexTrace.h +++ b/pcsx2/GS/Renderers/Common/GSVertexTrace.h @@ -15,7 +15,7 @@ class GSState; class GSVertexTrace; MULTI_ISA_DEF(class GSVertexTraceFMM;) -MULTI_ISA_DEF(void GSVertexTracePopulateFunctions(GSVertexTrace& vt, bool provoking_vertex_first);) +MULTI_ISA_DEF(void GSVertexTracePopulateFunctions(GSVertexTrace& vt);) class alignas(32) GSVertexTrace final : public GSAlignedClass<32> { @@ -63,7 +63,7 @@ public: GSVector2 m_lod = {}; // x = min, y = max public: - GSVertexTrace(const GSState* state, bool provoking_vertex_first); + GSVertexTrace(const GSState* state); void Update(const void* vertex, const u16* index, int v_count, int i_count, GS_PRIM_CLASS primclass); diff --git a/pcsx2/GS/Renderers/Common/GSVertexTraceFMM.cpp b/pcsx2/GS/Renderers/Common/GSVertexTraceFMM.cpp index 66bdb9565d..eac54474e8 100644 --- a/pcsx2/GS/Renderers/Common/GSVertexTraceFMM.cpp +++ b/pcsx2/GS/Renderers/Common/GSVertexTraceFMM.cpp @@ -9,41 +9,36 @@ class CURRENT_ISA::GSVertexTraceFMM { static constexpr GSVector4 s_minmax = GSVector4::cxpr(FLT_MAX, -FLT_MAX, 0.f, 0.f); - template + template static void FindMinMax(GSVertexTrace& vt, const void* vertex, const u16* index, int count); template - static constexpr GSVertexTrace::FindMinMaxPtr GetFMM(bool provoking_vertex_first); + static constexpr GSVertexTrace::FindMinMaxPtr GetFMM(); public: - static void Populate(GSVertexTrace& vt, bool provoking_vertex_first); + static void Populate(GSVertexTrace& vt); }; MULTI_ISA_UNSHARED_IMPL; -void CURRENT_ISA::GSVertexTracePopulateFunctions(GSVertexTrace& vt, bool provoking_vertex_first) +void CURRENT_ISA::GSVertexTracePopulateFunctions(GSVertexTrace& vt) { - GSVertexTraceFMM::Populate(vt, provoking_vertex_first); + GSVertexTraceFMM::Populate(vt); } template -constexpr GSVertexTrace::FindMinMaxPtr GSVertexTraceFMM::GetFMM(bool provoking_vertex_first) +constexpr GSVertexTrace::FindMinMaxPtr GSVertexTraceFMM::GetFMM() { constexpr bool real_iip = primclass == GS_SPRITE_CLASS ? false : iip; constexpr bool real_fst = tme ? fst : false; - constexpr bool provoking_vertex_first_class = primclass == GS_LINE_CLASS || primclass == GS_TRIANGLE_CLASS; - const bool swap = provoking_vertex_first_class && !iip && provoking_vertex_first; - if (swap) - return FindMinMax; - else - return FindMinMax; + return FindMinMax; } -void GSVertexTraceFMM::Populate(GSVertexTrace& vt, bool provoking_vertex_first) +void GSVertexTraceFMM::Populate(GSVertexTrace& vt) { #define InitUpdate3(P, IIP, TME, FST, COLOR) \ - vt.m_fmm[COLOR][FST][TME][IIP][P] = GetFMM(provoking_vertex_first); + vt.m_fmm[COLOR][FST][TME][IIP][P] = GetFMM(); #define InitUpdate2(P, IIP, TME) \ InitUpdate3(P, IIP, TME, 0, 0) \ @@ -63,7 +58,7 @@ void GSVertexTraceFMM::Populate(GSVertexTrace& vt, bool provoking_vertex_first) InitUpdate(GS_SPRITE_CLASS); } -template +template void GSVertexTraceFMM::FindMinMax(GSVertexTrace& vt, const void* vertex, const u16* index, int count) { const GSDrawingContext* context = vt.m_state->m_context; @@ -110,7 +105,7 @@ void GSVertexTraceFMM::FindMinMax(GSVertexTrace& vt, const void* vertex, const u { // For even n, we process v1 and v2 of the same prim // (For odd n, we process one vertex from each of two prims) - GSVector4i c = flat_swapped ? c0 : c1; + GSVector4i c = c1; // second color is provoking in flat-shaded primitives cmin = cmin.min_u8(c); cmax = cmax.max_u8(c); } @@ -196,26 +191,16 @@ void GSVertexTraceFMM::FindMinMax(GSVertexTrace& vt, const void* vertex, const u int i = 0; for (; i < (count - 3); i += 6) { - processVertices(v[index[i + 0]], v[index[i + 3]], flat_swapped); + processVertices(v[index[i + 0]], v[index[i + 3]], false); processVertices(v[index[i + 1]], v[index[i + 4]], false); - processVertices(v[index[i + 2]], v[index[i + 5]], !flat_swapped); + processVertices(v[index[i + 2]], v[index[i + 5]], true); } if (count & 1) { - if (flat_swapped) - { - processVertices(v[index[i + 1]], v[index[i + 2]], false); - // Compiler optimizations go! - // (And if they don't, it's only one vertex out of many) - processVertices(v[index[i + 0]], v[index[i + 0]], true); - } - else - { - processVertices(v[index[i + 0]], v[index[i + 1]], false); - // 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 + 0]], v[index[i + 1]], false); + // 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); } } else