From 019e276798243d41003d22c7cc4e78b9328ca439 Mon Sep 17 00:00:00 2001 From: xebra Date: Thu, 9 Aug 2018 19:29:19 +0900 Subject: [PATCH] [spline/bezier]Modify ControlPoints and fix VertexPreview. --- GPU/Common/SplineCommon.cpp | 35 +++--- GPU/Common/SplineCommon.h | 18 ++- Windows/GEDebugger/VertexPreview.cpp | 157 ++++++++++++++------------- 3 files changed, 112 insertions(+), 98 deletions(-) diff --git a/GPU/Common/SplineCommon.cpp b/GPU/Common/SplineCommon.cpp index 7d6d92ca26c1..76680aa314d0 100644 --- a/GPU/Common/SplineCommon.cpp +++ b/GPU/Common/SplineCommon.cpp @@ -21,7 +21,6 @@ #include "profiler/profiler.h" #include "Common/CPUDetect.h" -#include "Common/MemoryUtil.h" #include "GPU/Common/GPUStateUtils.h" #include "GPU/Common/SplineCommon.h" @@ -315,6 +314,22 @@ class SimpleBufferManager { } }; +ControlPoints::ControlPoints(const SimpleVertex *const *points, int size, SimpleBufferManager &managedBuf) { + pos = (Vec3f *)managedBuf.Allocate(sizeof(Vec3f) * size); + tex = (Vec2f *)managedBuf.Allocate(sizeof(Vec2f) * size); + col = (Vec4f *)managedBuf.Allocate(sizeof(Vec4f) * size); + Convert(points, size); +} + +void ControlPoints::Convert(const SimpleVertex *const *points, int size) { + for (int i = 0; i < size; ++i) { + pos[i] = Vec3f(points[i]->pos); + tex[i] = Vec2f(points[i]->uv); + col[i] = Vec4f::FromRGBA(points[i]->color_32); + } + defcolor = points[0]->color_32; +} + template class SubdivisionSurface { private: @@ -415,21 +430,13 @@ class SubdivisionSurface { }; template -static void SoftwareTessellation(OutputBuffers &output, const Patch &patch, u32 origVertType, - const SimpleVertex *const *points, SimpleBufferManager &managedBuf) { +void SoftwareTessellation(OutputBuffers &output, const Patch &patch, u32 origVertType, const ControlPoints &points) { using WeightType = Patch::WeightType; u32 key_u = WeightType::ToKey(patch.tess_u, patch.count_u, patch.type_u); u32 key_v = WeightType::ToKey(patch.tess_v, patch.count_v, patch.type_v); Weight2D weights(weightsCache, key_u, key_v); - int size = patch.count_u * patch.count_v; - ControlPoints cpoints; - cpoints.pos = (Vec3f *)managedBuf.Allocate(sizeof(Vec3f) * size); - cpoints.tex = (Vec2f *)managedBuf.Allocate(sizeof(Vec2f) * size); - cpoints.col = (Vec4f *)managedBuf.Allocate(sizeof(Vec4f) * size); - cpoints.Convert(points, size); - - SubdivisionSurface surface(cpoints, patch, weights); + SubdivisionSurface surface(points, patch, weights); surface.Tessellate(output, origVertType); } @@ -523,8 +530,9 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi HardwareTessellation(output, patch, origVertType, points, tessDataTransfer); numPatches = patch.num_patches_u * patch.num_patches_v; } else { + ControlPoints cpoints(points, count_u * count_v, managedBuf); patch.Init(SPLINE_BUFFER_SIZE / vertexSize); - SoftwareTessellation(output, patch, origVertType, points, managedBuf); + SoftwareTessellation(output, patch, origVertType, cpoints); } u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT; @@ -614,8 +622,9 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi HardwareTessellation(output, patch, origVertType, points, tessDataTransfer); numPatches = patch.num_patches_u * patch.num_patches_v; } else { + ControlPoints cpoints(points, count_u * count_v, managedBuf); patch.Init(SPLINE_BUFFER_SIZE / vertexSize); - SoftwareTessellation(output, patch, origVertType, points, managedBuf); + SoftwareTessellation(output, patch, origVertType, cpoints); } u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT; diff --git a/GPU/Common/SplineCommon.h b/GPU/Common/SplineCommon.h index 2d7b6cd4ae11..ed4a52677620 100644 --- a/GPU/Common/SplineCommon.h +++ b/GPU/Common/SplineCommon.h @@ -198,20 +198,17 @@ struct Weight2D { } }; +class SimpleBufferManager; + struct ControlPoints { Vec3f *pos; Vec2f *tex; Vec4f *col; u32_le defcolor; - void Convert(const SimpleVertex *const *points, int size) { - for (int i = 0; i < size; ++i) { - pos[i] = Vec3f(points[i]->pos); - tex[i] = Vec2f(points[i]->uv); - col[i] = Vec4f::FromRGBA(points[i]->color_32); - } - defcolor = points[0]->color_32; - } + ControlPoints() {} + ControlPoints(const SimpleVertex *const *points, int size, SimpleBufferManager &managedBuf); + void Convert(const SimpleVertex *const *points, int size); }; struct OutputBuffers { @@ -221,8 +218,9 @@ struct OutputBuffers { }; bool CanUseHardwareTessellation(GEPatchPrimType prim); -void TessellateSplinePatch(u8 *&dest, u16 *indices, int &count, 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); + +template +void SoftwareTessellation(OutputBuffers &output, const Patch &patch, u32 origVertType, const ControlPoints &points); // Define function object for TemplateParameterDispatcher #define TEMPLATE_PARAMETER_DISPATCHER_FUNCTION(NAME, FUNCNAME) \ diff --git a/Windows/GEDebugger/VertexPreview.cpp b/Windows/GEDebugger/VertexPreview.cpp index d7ea8f175565..c4c42f81ad88 100644 --- a/Windows/GEDebugger/VertexPreview.cpp +++ b/Windows/GEDebugger/VertexPreview.cpp @@ -26,6 +26,7 @@ #include "GPU/Common/GPUDebugInterface.h" #include "GPU/Common/SplineCommon.h" #include "GPU/GPUState.h" +#include "Common/MemoryUtil.h" static const char preview_fs[] = "#ifdef GL_ES\n" @@ -164,106 +165,112 @@ u32 CGEDebugger::PrimPreviewOp() { } static void ExpandBezier(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds) { - int count_u = (op & 0x00FF) >> 0; - int count_v = (op & 0xFF00) >> 8; + int count_u = (op >> 0) & 0xFF; + int count_v = (op >> 8) & 0xFF; + // Real hardware seems to draw nothing when given < 4 either U or V. + if (count_u < 4 || count_v < 4) + return; int tess_u = gstate.getPatchDivisionU(); int tess_v = gstate.getPatchDivisionV(); - if (tess_u < 1) { - tess_u = 1; - } - if (tess_v < 1) { - tess_v = 1; - } - - // Bezier patches share less control points than spline patches. Otherwise they are pretty much the same (except bezier don't support the open/close thing) - int num_patches_u = (count_u - 1) / 3; - int num_patches_v = (count_v - 1) / 3; - int total_patches = num_patches_u * num_patches_v; - - std::vector points(count_u * count_v); - for (int idx = 0; idx < count_u * count_v; idx++) - points[idx] = &simpleVerts[0] + (!indices.empty() ? indices[idx] : idx); + // If specified as 0, uses 1. + if (tess_u < 1) tess_u = 1; + if (tess_v < 1) tess_v = 1; BezierPatch patch; patch.count_u = count_u; patch.count_v = count_v; + patch.tess_u = tess_u; + patch.tess_v = tess_v; + patch.num_patches_u = (count_u - 1) / 3; + patch.num_patches_v = (count_v - 1) / 3; patch.primType = gstate.getPatchPrimitiveType(); patch.patchFacing = false; - patch.defcolor = 0xFFFFFFFF; - - std::vector pos(patch.count_u * patch.count_v); - std::vector tex(patch.count_u * patch.count_v); - std::vector col(patch.count_u * patch.count_v); - patch.pos = pos.data(); - patch.tex = tex.data(); - patch.col = col.data(); - for (int idx = 0; idx < count_u * count_v; idx++) { - patch.pos[idx] = Vec3f(points[idx]->pos); - patch.tex[idx] = Vec2f(points[idx]->uv); - patch.col[idx] = Vec4f::FromRGBA(points[idx]->color_32); - } + // Make an array of pointers to the control points, to get rid of indices. + std::vector points(count_u * count_v); + for (int idx = 0; idx < count_u * count_v; idx++) + points[idx] = simpleVerts.data() + (!indices.empty() ? indices[idx] : idx); + + int total_patches = patch.num_patches_u * patch.num_patches_v; generatedVerts.resize((tess_u + 1) * (tess_v + 1) * total_patches); generatedInds.resize(tess_u * tess_v * 6 * total_patches); - count = 0; - u8 *dest = (u8 *)&generatedVerts[0]; - u16 *inds = &generatedInds[0]; - TessellateBezierPatch(dest, inds, count, tess_u, tess_v, patch, gstate.vertType, generatedVerts.size()); + OutputBuffers output; + output.vertices = generatedVerts.data(); + output.indices = generatedInds.data(); + output.count = 0; + + int size = count_u * count_v; + ControlPoints cpoints; + cpoints.pos = (Vec3f *)AllocateAlignedMemory(sizeof(Vec3f) * size, 16); + cpoints.tex = (Vec2f *)AllocateAlignedMemory(sizeof(Vec2f) * size, 16); + cpoints.col = (Vec4f *)AllocateAlignedMemory(sizeof(Vec4f) * size, 16); + cpoints.Convert(points.data(), size); + + patch.Init(generatedVerts.size()); + SoftwareTessellation(output, patch, gstate.vertType, cpoints); + count = output.count; + + FreeAlignedMemory(cpoints.pos); + FreeAlignedMemory(cpoints.tex); + FreeAlignedMemory(cpoints.col); } static void ExpandSpline(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds) { - SplinePatchLocal patch; - patch.primType = gstate.getPatchPrimitiveType(); - patch.patchFacing = false; - - patch.count_u = (op & 0x00FF) >> 0; - patch.count_v = (op & 0xFF00) >> 8; - patch.type_u = (op >> 16) & 0x3; - patch.type_v = (op >> 18) & 0x3; - - patch.tess_u = gstate.getPatchDivisionU(); - patch.tess_v = gstate.getPatchDivisionV(); - if (patch.tess_u < 1) { - patch.tess_u = 1; - } - if (patch.tess_v < 1) { - patch.tess_v = 1; - } - + int count_u = (op >> 0) & 0xFF; + int count_v = (op >> 8) & 0xFF; // Real hardware seems to draw nothing when given < 4 either U or V. - if (patch.count_u < 4 || patch.count_v < 4) { + if (count_u < 4 || count_v < 4) return; - } - std::vector points(patch.count_u * patch.count_v); + int tess_u = gstate.getPatchDivisionU(); + int tess_v = gstate.getPatchDivisionV(); + // If specified as 0, uses 1. + if (tess_u < 1) tess_u = 1; + if (tess_v < 1) tess_v = 1; - // Make an array of pointers to the control points, to get rid of indices. - for (int idx = 0; idx < patch.count_u * patch.count_v; idx++) { - points[idx] = &simpleVerts[0] + (!indices.empty() ? indices[idx] : idx); - } - std::vector pos(patch.count_u * patch.count_v); - std::vector tex(patch.count_u * patch.count_v); - std::vector col(patch.count_u * patch.count_v); - patch.pos = pos.data(); - patch.tex = tex.data(); - patch.col = col.data(); - for (int idx = 0; idx < patch.count_u * patch.count_v; idx++) { - patch.pos[idx] = Vec3f(points[idx]->pos); - patch.tex[idx] = Vec2f(points[idx]->uv); - patch.col[idx] = Vec4f::FromRGBA(points[idx]->color_32); - } + SplinePatchLocal patch; + patch.count_u = count_u; + patch.count_v = count_v; + patch.tess_u = tess_u; + patch.tess_v = tess_v; + patch.type_u = (op >> 16) & 0x3; + patch.type_v = (op >> 18) & 0x3; + patch.num_patches_u = count_u - 3; + patch.num_patches_v = count_v - 3; + patch.primType = gstate.getPatchPrimitiveType(); + patch.patchFacing = false; - int patch_div_s = (patch.count_u - 3) * patch.tess_u; - int patch_div_t = (patch.count_v - 3) * patch.tess_v; + // Make an array of pointers to the control points, to get rid of indices. + std::vector points(count_u * count_v); + for (int idx = 0; idx < count_u * count_v; idx++) + points[idx] = simpleVerts.data() + (!indices.empty() ? indices[idx] : idx); + int patch_div_s = patch.num_patches_u * patch.tess_u; + int patch_div_t = patch.num_patches_v * patch.tess_v; generatedVerts.resize((patch_div_s + 1) * (patch_div_t + 1)); generatedInds.resize(patch_div_s * patch_div_t * 6); - count = 0; - u8 *dest = (u8 *)&generatedVerts[0]; - TessellateSplinePatch(dest, &generatedInds[0], count, patch, gstate.vertType, generatedVerts.size()); + OutputBuffers output; + output.vertices = generatedVerts.data(); + output.indices = generatedInds.data(); + output.count = 0; + + int size = count_u * count_v; + ControlPoints cpoints; + cpoints.pos = (Vec3f *)AllocateAlignedMemory(sizeof(Vec3f) * size, 16); + cpoints.tex = (Vec2f *)AllocateAlignedMemory(sizeof(Vec2f) * size, 16); + cpoints.col = (Vec4f *)AllocateAlignedMemory(sizeof(Vec4f) * size, 16); + cpoints.Convert(points.data(), size); + + patch.Init(generatedVerts.size()); + SoftwareTessellation(output, patch, gstate.vertType, cpoints); + count = output.count; + + FreeAlignedMemory(cpoints.pos); + FreeAlignedMemory(cpoints.tex); + FreeAlignedMemory(cpoints.col); } void CGEDebugger::UpdatePrimPreview(u32 op, int which) {