diff --git a/GPU/Common/SplineCommon.cpp b/GPU/Common/SplineCommon.cpp index 948c31b1f2b0..a4ce9f844d21 100644 --- a/GPU/Common/SplineCommon.cpp +++ b/GPU/Common/SplineCommon.cpp @@ -24,6 +24,7 @@ #include "Common/MemoryUtil.h" #include "Core/Config.h" +#include "GPU/Common/GPUStateUtils.h" #include "GPU/Common/SplineCommon.h" #include "GPU/Common/DrawEngineCommon.h" #include "GPU/ge_constants.h" @@ -223,6 +224,13 @@ static void spline_knot(int n, int type, float *knot) { } } +bool CanUseHardwareTessellation(GEPatchPrimType prim) { + if (g_Config.bHardwareTessellation && !g_Config.bSoftwareRendering) { + return CanUseHardwareTransform(PatchPrimToPrim(prim)); + } + return false; +} + // Prepare mesh of one patch for "Instanced Tessellation". static void TessellateSplinePatchHardware(u8 *&dest, u16 *indices, int &count, const SplinePatchLocal &spatch) { SimpleVertex *&vertices = (SimpleVertex*&)dest; @@ -841,9 +849,6 @@ void TessellateBezierPatch(u8 *&dest, u16 *&indices, int &count, int tess_u, int } } -// This maps GEPatchPrimType to GEPrimitiveType. -const GEPrimitiveType primType[] = { GE_PRIM_TRIANGLES, GE_PRIM_LINES, GE_PRIM_POINTS, GE_PRIM_POINTS }; - void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indices, int tess_u, int tess_v, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, bool computeNormals, bool patchFacing, u32 vertType, int *bytesRead) { PROFILE_THIS_SCOPE("spline"); DispatchFlush(); @@ -900,8 +905,7 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi patch.primType = prim_type; patch.patchFacing = patchFacing; - if (g_Config.bHardwareTessellation && g_Config.bHardwareTransform && !g_Config.bSoftwareRendering) { - + if (CanUseHardwareTessellation(prim_type)) { float *pos = (float*)(decoded + 65536 * 18); // Size 4 float float *tex = pos + count_u * count_v * 4; // Size 4 float float *col = tex + count_u * count_v * 4; // Size 4 float @@ -952,7 +956,7 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode()); int generatedBytesRead; - DispatchSubmitPrim(splineBuffer, quadIndices_, primType[prim_type], count, vertTypeID, &generatedBytesRead); + DispatchSubmitPrim(splineBuffer, quadIndices_, PatchPrimToPrim(prim_type), count, vertTypeID, &generatedBytesRead); DispatchFlush(); @@ -1006,7 +1010,7 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi int num_patches_u = (count_u - 1) / 3; int num_patches_v = (count_v - 1) / 3; BezierPatch *patches = nullptr; - if (g_Config.bHardwareTessellation && g_Config.bHardwareTransform && !g_Config.bSoftwareRendering) { + if (CanUseHardwareTessellation(prim_type)) { int posStride, texStride, colStride; tessDataTransfer->PrepareBuffers(pos, tex, col, posStride, texStride, colStride, count_u * count_v, hasColor, hasTexCoords); float *p = pos; @@ -1063,7 +1067,7 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi } u16 *inds = quadIndices_; - if (g_Config.bHardwareTessellation && g_Config.bHardwareTransform && !g_Config.bSoftwareRendering) { + if (CanUseHardwareTessellation(prim_type)) { tessDataTransfer->SendDataToShader(pos, tex, col, count_u * count_v, hasColor, hasTexCoords); TessellateBezierPatchHardware(dest, inds, count, tess_u, tess_v, prim_type); numPatches = num_patches_u * num_patches_v; @@ -1095,7 +1099,7 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode()); int generatedBytesRead; - DispatchSubmitPrim(splineBuffer, quadIndices_, primType[prim_type], count, vertTypeID, &generatedBytesRead); + DispatchSubmitPrim(splineBuffer, quadIndices_, PatchPrimToPrim(prim_type), count, vertTypeID, &generatedBytesRead); DispatchFlush(); diff --git a/GPU/Common/SplineCommon.h b/GPU/Common/SplineCommon.h index 7291f5bc9f12..52bf75b69bca 100644 --- a/GPU/Common/SplineCommon.h +++ b/GPU/Common/SplineCommon.h @@ -66,5 +66,6 @@ enum SplineQuality { HIGH_QUALITY = 2, }; +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); diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index be7ffd9e83d0..fb7b001b7bff 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -325,14 +325,15 @@ void DrawEngineD3D11::DoFlush() { gpuStats.numFlushes++; gpuStats.numTrackedVertexArrays = (int)vai_.size(); - // This is not done on every drawcall, we should collect vertex data + // This is not done on every drawcall, we collect vertex data // until critical state changes. That's when we draw (flush). GEPrimitiveType prim = prevPrim_; ApplyDrawState(prim); // Always use software for flat shading to fix the provoking index. - bool useHWTransform = CanUseHardwareTransform(prim) && gstate.getShadeMode() != GE_SHADE_FLAT; + bool tess = gstate_c.bezier || gstate_c.spline; + bool useHWTransform = CanUseHardwareTransform(prim) && (tess || gstate.getShadeMode() != GE_SHADE_FLAT); if (useHWTransform) { ID3D11Buffer *vb_ = nullptr; @@ -539,7 +540,7 @@ void DrawEngineD3D11::DoFlush() { memcpy(iptr, decIndex, iSize); pushInds_->EndPush(context_); context_->IASetIndexBuffer(pushInds_->Buf(), DXGI_FORMAT_R16_UINT, iOffset); - if (gstate_c.bezier || gstate_c.spline) + if (tess) context_->DrawIndexedInstanced(vertexCount, numPatches, 0, 0, 0); else context_->DrawIndexed(vertexCount, 0, 0); @@ -551,7 +552,7 @@ void DrawEngineD3D11::DoFlush() { context_->IASetVertexBuffers(0, 1, &vb_, &stride, &offset); if (useElements) { context_->IASetIndexBuffer(ib_, DXGI_FORMAT_R16_UINT, 0); - if (gstate_c.bezier || gstate_c.spline) + if (tess) context_->DrawIndexedInstanced(vertexCount, numPatches, 0, 0, 0); else context_->DrawIndexed(vertexCount, 0, 0); diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index f910f6cc8f04..2e01495aa297 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -538,7 +538,8 @@ void ShaderManagerDX9::DirtyLastShader() { // disables vertex arrays VSShader *ShaderManagerDX9::ApplyShader(int prim, u32 vertType) { // Always use software for flat shading to fix the provoking index. - bool useHWTransform = CanUseHardwareTransform(prim) && gstate.getShadeMode() != GE_SHADE_FLAT; + bool tess = gstate_c.bezier || gstate_c.spline; + bool useHWTransform = CanUseHardwareTransform(prim) && (tess || gstate.getShadeMode() != GE_SHADE_FLAT); VShaderID VSID; if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) { diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 5eb2cc595b13..9a6a471ae84a 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -24,9 +24,10 @@ #include "Core/HLE/sceGe.h" #include "Core/Debugger/Breakpoints.h" #include "Core/MemMapHelpers.h" +#include "GPU/Common/DrawEngineCommon.h" #include "GPU/Common/FramebufferCommon.h" +#include "GPU/Common/SplineCommon.h" #include "GPU/Common/TextureCacheCommon.h" -#include "GPU/Common/DrawEngineCommon.h" #include "GPU/Debugger/Record.h" const CommonCommandTableEntry commonCommandTable[] = { @@ -1729,7 +1730,7 @@ void GPUCommon::Execute_Bezier(u32 op, u32 diff) { bool computeNormals = gstate.isLightingEnabled(); bool patchFacing = gstate.patchfacing & 1; - if (g_Config.bHardwareTessellation && g_Config.bHardwareTransform && !g_Config.bSoftwareRendering) { + if (CanUseHardwareTessellation(patchPrim)) { gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE); gstate_c.bezier = true; if (gstate_c.spline_count_u != bz_ucount) { @@ -1793,7 +1794,7 @@ void GPUCommon::Execute_Spline(u32 op, u32 diff) { bool patchFacing = gstate.patchfacing & 1; u32 vertType = gstate.vertType; - if (g_Config.bHardwareTessellation && g_Config.bHardwareTransform && !g_Config.bSoftwareRendering) { + if (CanUseHardwareTessellation(patchPrim)) { gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE); gstate_c.spline = true; bool countsChanged = gstate_c.spline_count_u != sp_ucount || gstate_c.spline_count_v != sp_vcount; diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 405c10fc54f0..0da871ba3eb4 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -578,7 +578,7 @@ void DrawEngineVulkan::DoFlush() { GEPrimitiveType prim = prevPrim_; // Always use software for flat shading to fix the provoking index. - bool useHWTransform = CanUseHardwareTransform(prim) && gstate.getShadeMode() != GE_SHADE_FLAT; + bool useHWTransform = CanUseHardwareTransform(prim) && (tess || gstate.getShadeMode() != GE_SHADE_FLAT); VulkanVertexShader *vshader = nullptr; VulkanFragmentShader *fshader = nullptr; diff --git a/GPU/ge_constants.h b/GPU/ge_constants.h index 1bba05640d5c..c0b1bc067e86 100644 --- a/GPU/ge_constants.h +++ b/GPU/ge_constants.h @@ -563,7 +563,7 @@ inline GEPrimitiveType PatchPrimToPrim(GEPatchPrimType type) { case GE_PATCHPRIM_TRIANGLES: return GE_PRIM_TRIANGLES; case GE_PATCHPRIM_LINES: return GE_PRIM_LINES; case GE_PATCHPRIM_POINTS: return GE_PRIM_POINTS; - case GE_PATCHPRIM_UNKNOWN: default: return GE_PRIM_KEEP_PREVIOUS; // just something + case GE_PATCHPRIM_UNKNOWN: default: return GE_PRIM_POINTS; // Treated as points. } }