From 04708fe88afab5259f41bfdc0faf98e400146b64 Mon Sep 17 00:00:00 2001 From: xebra Date: Tue, 13 Nov 2018 17:12:41 +0900 Subject: [PATCH] [spline/bezier]Unify SubmitSpline/Bezier. --- GPU/Common/DrawEngineCommon.h | 4 +- GPU/Common/SplineCommon.cpp | 112 +++------------------------------- GPU/GPUCommon.cpp | 58 ++++++++++-------- GPU/Software/SoftGpu.cpp | 47 ++++++++------ 4 files changed, 73 insertions(+), 148 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 353b3dd7d0..21a3d06b2c 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -81,8 +81,8 @@ public: bool TestBoundingBox(void* control_points, int vertexCount, u32 vertType, int *bytesRead); void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead); - void 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); - void SubmitBezier(const void *control_points, const void *indices, int tess_u, int tess_v, int count_u, int count_v, GEPatchPrimType prim_type, bool computeNormals, bool patchFacing, u32 vertType, int *bytesRead); + template + void SubmitCurve(const void *control_points, const void *indices, Surface &surface, u32 vertType, int *bytesRead, const char *scope); void ClearSplineBezierWeights(); std::vector DebugGetVertexLoaderIDs(); diff --git a/GPU/Common/SplineCommon.cpp b/GPU/Common/SplineCommon.cpp index 77427b99ee..73104649e5 100644 --- a/GPU/Common/SplineCommon.cpp +++ b/GPU/Common/SplineCommon.cpp @@ -488,106 +488,23 @@ void DrawEngineCommon::ClearSplineBezierWeights() { Spline3DWeight::weightsCache.Clear(); } -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(); +// Specialize to make instance (to avoid link error). +template void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indices, BezierSurface &surface, u32 vertType, int *bytesRead, const char *scope); +template void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indices, SplineSurface &surface, u32 vertType, int *bytesRead, const char *scope); - // Real hardware seems to draw nothing when given < 4 either U or V. - if (count_u < 4 || count_v < 4) - return; - - SimpleBufferManager managedBuf(decoded, DECODED_VERTEX_BUFFER_SIZE / 2); - - int num_points = count_u * count_v; - u16 index_lower_bound = 0; - u16 index_upper_bound = num_points - 1; - IndexConverter ConvertIndex(vertType, indices); - if (indices) - GetIndexBounds(indices, num_points, vertType, &index_lower_bound, &index_upper_bound); - - VertexDecoder *origVDecoder = GetVertexDecoder((vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24)); - *bytesRead = num_points * origVDecoder->VertexSize(); - - // Simplify away bones and morph before proceeding - SimpleVertex *simplified_control_points = (SimpleVertex *)managedBuf.Allocate(sizeof(SimpleVertex) * (index_upper_bound + 1)); - u8 *temp_buffer = managedBuf.Allocate(sizeof(SimpleVertex) * num_points); - - u32 origVertType = vertType; - vertType = NormalizeVertices((u8 *)simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, vertType); - - VertexDecoder *vdecoder = GetVertexDecoder(vertType); - - int vertexSize = vdecoder->VertexSize(); - if (vertexSize != sizeof(SimpleVertex)) { - ERROR_LOG(G3D, "Something went really wrong, vertex size: %i vs %i", vertexSize, (int)sizeof(SimpleVertex)); - } - - // Make an array of pointers to the control points, to get rid of indices. - const SimpleVertex **points = (const SimpleVertex **)managedBuf.Allocate(sizeof(SimpleVertex *) * num_points); - for (int idx = 0; idx < num_points; idx++) - points[idx] = simplified_control_points + (indices ? ConvertIndex(idx) : idx); - - OutputBuffers output; - output.vertices = (SimpleVertex *)(decoded + DECODED_VERTEX_BUFFER_SIZE / 2); - output.indices = decIndex; - output.count = 0; - - SplineSurface surface; - surface.tess_u = tess_u; - surface.tess_v = tess_v; - surface.type_u = type_u; - surface.type_v = type_v; - surface.num_points_u = count_u; - surface.num_points_v = count_v; - surface.num_patches_u = count_u - 3; - surface.num_patches_v = count_v - 3; - surface.primType = prim_type; - surface.patchFacing = patchFacing; - surface.Init(DECODED_VERTEX_BUFFER_SIZE / 2 / vertexSize); - - if (CanUseHardwareTessellation(prim_type)) { - HardwareTessellation(output, surface, origVertType, points, tessDataTransfer); - } else { - ControlPoints cpoints(points, num_points, managedBuf); - SoftwareTessellation(output, surface, origVertType, cpoints); - } - - u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT; - - UVScale prevUVScale; - if ((origVertType & GE_VTYPE_TC_MASK) != 0) { - // We scaled during Normalize already so let's turn it off when drawing. - prevUVScale = gstate_c.uv; - gstate_c.uv.uScale = 1.0f; - gstate_c.uv.vScale = 1.0f; - gstate_c.uv.uOff = 0.0f; - gstate_c.uv.vOff = 0.0f; - } - - uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode()); - - int generatedBytesRead; - DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(prim_type), output.count, vertTypeID, &generatedBytesRead); - - DispatchFlush(); - - if ((origVertType & GE_VTYPE_TC_MASK) != 0) { - gstate_c.uv = prevUVScale; - } -} - -void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indices, int tess_u, int tess_v, int count_u, int count_v, GEPatchPrimType prim_type, bool computeNormals, bool patchFacing, u32 vertType, int *bytesRead) { - PROFILE_THIS_SCOPE("bezier"); +template +void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indices, Surface &surface, u32 vertType, int *bytesRead, const char *scope) { + PROFILE_THIS_SCOPE(scope); DispatchFlush(); // Real hardware seems to draw nothing when given < 4 either U or V. // This would result in num_patches_u / num_patches_v being 0. - if (count_u < 4 || count_v < 4) + if (surface.num_points_u < 4 || surface.num_points_v < 4) return; SimpleBufferManager managedBuf(decoded, DECODED_VERTEX_BUFFER_SIZE / 2); - int num_points = count_u * count_v; + int num_points = surface.num_points_u * surface.num_points_v; u16 index_lower_bound = 0; u16 index_upper_bound = num_points - 1; IndexConverter ConvertIndex(vertType, indices); @@ -622,18 +539,9 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi output.indices = decIndex; output.count = 0; - BezierSurface surface; - surface.tess_u = tess_u; - surface.tess_v = tess_v; - surface.num_points_u = count_u; - surface.num_points_v = count_v; - surface.num_patches_u = (count_u - 1) / 3; - surface.num_patches_v = (count_v - 1) / 3; - surface.primType = prim_type; - surface.patchFacing = patchFacing; surface.Init(DECODED_VERTEX_BUFFER_SIZE / 2 / vertexSize); - if (CanUseHardwareTessellation(prim_type)) { + if (CanUseHardwareTessellation(surface.primType)) { HardwareTessellation(output, surface, origVertType, points, tessDataTransfer); } else { ControlPoints cpoints(points, num_points, managedBuf); @@ -654,7 +562,7 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode()); int generatedBytesRead; - DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(prim_type), output.count, vertTypeID, &generatedBytesRead); + DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(surface.primType), output.count, vertTypeID, &generatedBytesRead); DispatchFlush(); diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 2fb07c9ae9..1e58cb2a6e 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1747,33 +1747,37 @@ void GPUCommon::Execute_Bezier(u32 op, u32 diff) { DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType)); } - GEPatchPrimType patchPrim = gstate.getPatchPrimitiveType(); - SetDrawType(DRAW_BEZIER, PatchPrimToPrim(patchPrim)); + Spline::BezierSurface surface; + surface.tess_u = gstate.getPatchDivisionU(); + surface.tess_v = gstate.getPatchDivisionV(); + surface.num_points_u = op & 0xFF; + surface.num_points_v = (op >> 8) & 0xFF; + surface.num_patches_u = (surface.num_points_u - 1) / 3; + surface.num_patches_v = (surface.num_points_v - 1) / 3; + surface.primType = gstate.getPatchPrimitiveType(); + surface.patchFacing = gstate.patchfacing & 1; - int bz_ucount = op & 0xFF; - int bz_vcount = (op >> 8) & 0xFF; - bool computeNormals = gstate.isLightingEnabled(); - bool patchFacing = gstate.patchfacing & 1; + SetDrawType(DRAW_BEZIER, PatchPrimToPrim(surface.primType)); - if (CanUseHardwareTessellation(patchPrim)) { + if (CanUseHardwareTessellation(surface.primType)) { gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE); gstate_c.bezier = true; - if (gstate_c.spline_num_points_u != bz_ucount) { + if (gstate_c.spline_num_points_u != surface.num_points_u) { gstate_c.Dirty(DIRTY_BEZIERSPLINE); - gstate_c.spline_num_points_u = bz_ucount; + gstate_c.spline_num_points_u = surface.num_points_u; } } int bytesRead = 0; UpdateUVScaleOffset(); - drawEngineCommon_->SubmitBezier(control_points, indices, gstate.getPatchDivisionU(), gstate.getPatchDivisionV(), bz_ucount, bz_vcount, patchPrim, computeNormals, patchFacing, gstate.vertType, &bytesRead); + drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "bezier"); if (gstate_c.bezier) gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE); gstate_c.bezier = false; // After drawing, we advance pointers - see SubmitPrim which does the same. - int count = bz_ucount * bz_vcount; + int count = surface.num_points_u * surface.num_points_v; AdvanceVerts(gstate.vertType, count, bytesRead); } @@ -1807,35 +1811,39 @@ void GPUCommon::Execute_Spline(u32 op, u32 diff) { DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType)); } - int sp_ucount = op & 0xFF; - int sp_vcount = (op >> 8) & 0xFF; - int sp_utype = (op >> 16) & 0x3; - int sp_vtype = (op >> 18) & 0x3; - GEPatchPrimType patchPrim = gstate.getPatchPrimitiveType(); - SetDrawType(DRAW_SPLINE, PatchPrimToPrim(patchPrim)); - bool computeNormals = gstate.isLightingEnabled(); - bool patchFacing = gstate.patchfacing & 1; - u32 vertType = gstate.vertType; + Spline::SplineSurface surface; + surface.tess_u = gstate.getPatchDivisionU(); + surface.tess_v = gstate.getPatchDivisionV(); + surface.type_u = (op >> 16) & 0x3; + surface.type_v = (op >> 18) & 0x3; + surface.num_points_u = op & 0xFF; + surface.num_points_v = (op >> 8) & 0xFF; + surface.num_patches_u = surface.num_points_u - 3; + surface.num_patches_v = surface.num_points_v - 3; + surface.primType = gstate.getPatchPrimitiveType(); + surface.patchFacing = gstate.patchfacing & 1; - if (CanUseHardwareTessellation(patchPrim)) { + SetDrawType(DRAW_SPLINE, PatchPrimToPrim(surface.primType)); + + if (CanUseHardwareTessellation(surface.primType)) { gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE); gstate_c.spline = true; - if (gstate_c.spline_num_points_u != sp_ucount) { + if (gstate_c.spline_num_points_u != surface.num_points_u) { gstate_c.Dirty(DIRTY_BEZIERSPLINE); - gstate_c.spline_num_points_u = sp_ucount; + gstate_c.spline_num_points_u = surface.num_points_u; } } int bytesRead = 0; UpdateUVScaleOffset(); - drawEngineCommon_->SubmitSpline(control_points, indices, gstate.getPatchDivisionU(), gstate.getPatchDivisionV(), sp_ucount, sp_vcount, sp_utype, sp_vtype, patchPrim, computeNormals, patchFacing, vertType, &bytesRead); + drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "spline"); if (gstate_c.spline) gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE); gstate_c.spline = false; // After drawing, we advance pointers - see SubmitPrim which does the same. - int count = sp_ucount * sp_vcount; + int count = surface.num_points_u * surface.num_points_v; AdvanceVerts(gstate.vertType, count, bytesRead); } diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 2673ef4ab2..44771c197b 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -38,6 +38,7 @@ #include "GPU/Software/TransformUnit.h" #include "GPU/Common/DrawEngineCommon.h" #include "GPU/Common/FramebufferCommon.h" +#include "GPU/Common/SplineCommon.h" #include "GPU/Debugger/Debugger.h" #include "GPU/Debugger/Record.h" @@ -401,20 +402,24 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) { DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType)); } - GEPatchPrimType patchPrim = gstate.getPatchPrimitiveType(); - SetDrawType(DRAW_BEZIER, PatchPrimToPrim(patchPrim)); + Spline::BezierSurface surface; + surface.tess_u = gstate.getPatchDivisionU(); + surface.tess_v = gstate.getPatchDivisionV(); + surface.num_points_u = op & 0xFF; + surface.num_points_v = (op >> 8) & 0xFF; + surface.num_patches_u = (surface.num_points_u - 1) / 3; + surface.num_patches_v = (surface.num_points_v - 1) / 3; + surface.primType = gstate.getPatchPrimitiveType(); + surface.patchFacing = gstate.patchfacing & 1; - int bz_ucount = op & 0xFF; - int bz_vcount = (op >> 8) & 0xFF; - bool computeNormals = gstate.isLightingEnabled(); - bool patchFacing = gstate.patchfacing & 1; + SetDrawType(DRAW_BEZIER, PatchPrimToPrim(surface.primType)); int bytesRead = 0; - drawEngineCommon_->SubmitBezier(control_points, indices, gstate.getPatchDivisionU(), gstate.getPatchDivisionV(), bz_ucount, bz_vcount, patchPrim, computeNormals, patchFacing, gstate.vertType, &bytesRead); + drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "bezier"); framebufferDirty_ = true; // After drawing, we advance pointers - see SubmitPrim which does the same. - int count = bz_ucount * bz_vcount; + int count = surface.num_points_u * surface.num_points_v; AdvanceVerts(gstate.vertType, count, bytesRead); } break; @@ -449,22 +454,26 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) { DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType)); } - int sp_ucount = op & 0xFF; - int sp_vcount = (op >> 8) & 0xFF; - int sp_utype = (op >> 16) & 0x3; - int sp_vtype = (op >> 18) & 0x3; - GEPatchPrimType patchPrim = gstate.getPatchPrimitiveType(); - SetDrawType(DRAW_SPLINE, PatchPrimToPrim(patchPrim)); - bool computeNormals = gstate.isLightingEnabled(); - bool patchFacing = gstate.patchfacing & 1; - u32 vertType = gstate.vertType; + Spline::SplineSurface surface; + surface.tess_u = gstate.getPatchDivisionU(); + surface.tess_v = gstate.getPatchDivisionV(); + surface.type_u = (op >> 16) & 0x3; + surface.type_v = (op >> 18) & 0x3; + surface.num_points_u = op & 0xFF; + surface.num_points_v = (op >> 8) & 0xFF; + surface.num_patches_u = surface.num_points_u - 3; + surface.num_patches_v = surface.num_points_v - 3; + surface.primType = gstate.getPatchPrimitiveType(); + surface.patchFacing = gstate.patchfacing & 1; + + SetDrawType(DRAW_SPLINE, PatchPrimToPrim(surface.primType)); int bytesRead = 0; - drawEngineCommon_->SubmitSpline(control_points, indices, gstate.getPatchDivisionU(), gstate.getPatchDivisionV(), sp_ucount, sp_vcount, sp_utype, sp_vtype, patchPrim, computeNormals, patchFacing, vertType, &bytesRead); + drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "spline"); framebufferDirty_ = true; // After drawing, we advance pointers - see SubmitPrim which does the same. - int count = sp_ucount * sp_vcount; + int count = surface.num_points_u * surface.num_points_v; AdvanceVerts(gstate.vertType, count, bytesRead); } break;