diff --git a/GPU/Common/SplineCommon.cpp b/GPU/Common/SplineCommon.cpp index 83cef3336292..592baf369522 100644 --- a/GPU/Common/SplineCommon.cpp +++ b/GPU/Common/SplineCommon.cpp @@ -410,53 +410,31 @@ static void SplinePatchFullQuality(u8 *&dest, u16 *indices, int &count, const Sp BuildIndex(indices, count, patch_div_s, patch_div_t, spatch.primType); } -template -static inline void SplinePatchFullQualityDispatch4(u8 *&dest, u16 *indices, int &count, const SplinePatchLocal &spatch, u32 origVertType, int quality, int maxVertices) { - if (cpu_info.bSSE4_1) - SplinePatchFullQuality(dest, indices, count, spatch, origVertType, quality, maxVertices); - else - SplinePatchFullQuality(dest, indices, count, spatch, origVertType, quality, maxVertices); -} - -template -static inline void SplinePatchFullQualityDispatch3(u8 *&dest, u16 *indices, int &count, const SplinePatchLocal &spatch, u32 origVertType, int quality, int maxVertices) { - bool origTc = (origVertType & GE_VTYPE_TC_MASK) != 0; - - if (origTc) - SplinePatchFullQualityDispatch4(dest, indices, count, spatch, origVertType, quality, maxVertices); - else - SplinePatchFullQualityDispatch4(dest, indices, count, spatch, origVertType, quality, maxVertices); -} - -template -static inline void SplinePatchFullQualityDispatch2(u8 *&dest, u16 *indices, int &count, const SplinePatchLocal &spatch, u32 origVertType, int quality, int maxVertices) { - bool origCol = (origVertType & GE_VTYPE_COL_MASK) != 0; - - if (origCol) - SplinePatchFullQualityDispatch3(dest, indices, count, spatch, origVertType, quality, maxVertices); - else - SplinePatchFullQualityDispatch3(dest, indices, count, spatch, origVertType, quality, maxVertices); -} - -static void SplinePatchFullQualityDispatch(u8 *&dest, u16 *indices, int &count, const SplinePatchLocal &spatch, u32 origVertType, int quality, int maxVertices) { - bool origNrm = (origVertType & GE_VTYPE_NRM_MASK) != 0; - - if (origNrm) - SplinePatchFullQualityDispatch2(dest, indices, count, spatch, origVertType, quality, maxVertices); - else - SplinePatchFullQualityDispatch2(dest, indices, count, spatch, origVertType, quality, maxVertices); -} +// Define class TemplateParameterDispatcherTess +TEMPLATE_PARAMETER_DISPATCHER(Tess, SplinePatchFullQuality); void TessellateSplinePatch(u8 *&dest, u16 *indices, int &count, const SplinePatchLocal &spatch, u32 origVertType, int maxVertexCount) { + using TessFunc = void(*)(u8 *&, u16 *, int &, const SplinePatchLocal &, u32, int, int); + constexpr int NumParams = 4; + static TemplateParameterDispatcherTess dispatcher; // Initialize only once + + const bool params[NumParams] = { + (origVertType & GE_VTYPE_NRM_MASK) != 0, + (origVertType & GE_VTYPE_COL_MASK) != 0, + (origVertType & GE_VTYPE_TC_MASK) != 0, + cpu_info.bSSE4_1, + }; + TessFunc func = dispatcher.GetFunc(params); + switch (g_Config.iSplineBezierQuality) { case LOW_QUALITY: - SplinePatchFullQualityDispatch(dest, indices, count, spatch, origVertType, 0, maxVertexCount); + (*func)(dest, indices, count, spatch, origVertType, 0, maxVertexCount); break; case MEDIUM_QUALITY: - SplinePatchFullQualityDispatch(dest, indices, count, spatch, origVertType, 2, maxVertexCount); + (*func)(dest, indices, count, spatch, origVertType, 2, maxVertexCount); break; case HIGH_QUALITY: - SplinePatchFullQualityDispatch(dest, indices, count, spatch, origVertType, 1, maxVertexCount); + (*func)(dest, indices, count, spatch, origVertType, 1, maxVertexCount); break; } } diff --git a/GPU/Common/SplineCommon.h b/GPU/Common/SplineCommon.h index 9cd99ebcb499..a0e208f463a3 100644 --- a/GPU/Common/SplineCommon.h +++ b/GPU/Common/SplineCommon.h @@ -69,3 +69,40 @@ enum SplineQuality { bool CanUseHardwareTessellation(GEPatchPrimType prim); void TessellateSplinePatch(u8 *&dest, u16 *indices, int &count, const SplinePatchLocal &spatch, u32 origVertType, int maxVertices); +void TessellateBezierPatch(u8 *&dest, u16 *&indices, int &count, int tess_u, int tess_v, const BezierPatch &patch, u32 origVertType, int maxVertices); + +#define TEMPLATE_PARAMETER_DISPATCHER(NAME, FUNCNAME) \ +template \ +class TemplateParameterDispatcher##NAME { \ + /* Store all combinations of template functions into an array */ \ + template \ + struct Initializer { \ + Initializer(Func funcs[]) { \ + Initializer _true(funcs); \ + Initializer _false(funcs); \ + } \ + }; \ + /* Specialized for terminates the recursive loop */ \ + template \ + struct Initializer<0, Index, Params...> { \ + Initializer(Func funcs[]) { \ + funcs[Index] = &FUNCNAME; \ + } \ + }; \ + \ +private: \ + Func funcs[1 << NumParams]; /* Function pointers array */ \ +public: \ + TemplateParameterDispatcher##NAME() { \ + Initializer::Initializer(funcs); \ + } \ + \ + Func GetFunc(const bool params[]) const { \ + /* Convert bool parameters to index of the array */ \ + int param = 0; \ + for (int i = 0; i < NumParams; ++i) \ + param |= params[i] << i; \ + \ + return funcs[param]; \ + } \ +};