diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index c2bc891845..349b9ff958 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -27,7 +27,6 @@ #include "GPU/Common/GPUDebugInterface.h" #include "GPU/Common/IndexGenerator.h" #include "GPU/Common/VertexDecoderCommon.h" -#include "GPU/Common/SplineCommon.h" class VertexDecoder; @@ -52,11 +51,12 @@ inline uint32_t GetVertTypeID(uint32_t vertType, int uvGenMode) { } struct SimpleVertex; +namespace Spline { struct Weight2D; } class TessellationDataTransfer { public: void CopyControlPoints(float *pos, float *tex, float *col, int posStride, int texStride, int colStride, const SimpleVertex *const *points, int size, u32 vertType); - virtual void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) = 0; + virtual void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) = 0; }; class DrawEngineCommon { diff --git a/GPU/Common/SplineCommon.cpp b/GPU/Common/SplineCommon.cpp index 80d9bad20c..449d58f723 100644 --- a/GPU/Common/SplineCommon.cpp +++ b/GPU/Common/SplineCommon.cpp @@ -28,6 +28,35 @@ #include "GPU/ge_constants.h" #include "GPU/GPUState.h" // only needed for UVScale stuff +bool CanUseHardwareTessellation(GEPatchPrimType prim) { + if (g_Config.bHardwareTessellation && !g_Config.bSoftwareRendering) { + return CanUseHardwareTransform(PatchPrimToPrim(prim)); + } + return false; +} + +class SimpleBufferManager { +private: + u8 *buf_; + size_t totalSize, maxSize_; +public: + SimpleBufferManager(u8 *buf, size_t maxSize) + : buf_(buf), totalSize(0), maxSize_(maxSize) {} + + u8 *Allocate(size_t size) { + size = (size + 15) & ~15; // Align for 16 bytes + + if ((totalSize + size) > maxSize_) + return nullptr; // No more memory + + size_t tmp = totalSize; + totalSize += size; + return buf_ + tmp; + } +}; + +namespace Spline { + static void CopyQuadIndex(u16 *&indices, GEPatchPrimType type, const int idx0, const int idx1, const int idx2, const int idx3) { if (type == GE_PATCHPRIM_LINES) { *(indices++) = idx0; @@ -256,18 +285,6 @@ public: WeightCache Bezier3DWeight::weightsCache; WeightCache Spline3DWeight::weightsCache; -void DrawEngineCommon::ClearSplineBezierWeights() { - Bezier3DWeight::weightsCache.Clear(); - Spline3DWeight::weightsCache.Clear(); -} - -bool CanUseHardwareTessellation(GEPatchPrimType prim) { - if (g_Config.bHardwareTessellation && !g_Config.bSoftwareRendering) { - return CanUseHardwareTransform(PatchPrimToPrim(prim)); - } - return false; -} - // Tessellate single patch (4x4 control points) template class Tessellator { @@ -307,26 +324,6 @@ public: } }; -class SimpleBufferManager { -private: - u8 *buf_; - size_t totalSize, maxSize_; -public: - SimpleBufferManager(u8 *buf, size_t maxSize) - : buf_(buf), totalSize(0), maxSize_(maxSize) {} - - u8 *Allocate(size_t size) { - size = (size + 15) & ~15; // Align for 16 bytes - - if ((totalSize + size) > maxSize_) - return nullptr; // No more memory - - size_t tmp = totalSize; - totalSize += size; - return buf_ + tmp; - } -}; - ControlPoints::ControlPoints(const SimpleVertex *const *points, int size, SimpleBufferManager &managedBuf) { pos = (Vec3f *)managedBuf.Allocate(sizeof(Vec3f) * size); tex = (Vec2f *)managedBuf.Allocate(sizeof(Vec2f) * size); @@ -482,6 +479,15 @@ static void HardwareTessellation(OutputBuffers &output, const Surface &surface, surface.BuildIndex(output.indices, output.count); } +} + +using namespace Spline; + +void DrawEngineCommon::ClearSplineBezierWeights() { + Bezier3DWeight::weightsCache.Clear(); + 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(); diff --git a/GPU/Common/SplineCommon.h b/GPU/Common/SplineCommon.h index fdac8b7831..1d534cf215 100644 --- a/GPU/Common/SplineCommon.h +++ b/GPU/Common/SplineCommon.h @@ -37,6 +37,10 @@ struct SimpleVertex { Vec3Packedf pos; }; +class SimpleBufferManager; + +namespace Spline { + void BuildIndex(u16 *indices, int &count, int num_u, int num_v, GEPatchPrimType prim_type, int total = 0); enum SplineQuality { @@ -110,7 +114,7 @@ struct BezierSurface : public SurfaceInfo { for (int patch_v = 0; patch_v < num_patches_v; ++patch_v) { int patch_index = patch_v * num_patches_u + patch_u; int total = patch_index * num_verts_per_patch; - ::BuildIndex(indices + count, count, tess_u, tess_v, primType, total); + Spline::BuildIndex(indices + count, count, tess_u, tess_v, primType, total); } } } @@ -143,7 +147,7 @@ struct SplineSurface : public SurfaceInfo { } void BuildIndex(u16 *indices, int &count) const { - ::BuildIndex(indices, count, num_patches_u * tess_u, num_patches_v * tess_v, primType); + Spline::BuildIndex(indices, count, num_patches_u * tess_u, num_patches_v * tess_v, primType); } }; @@ -181,8 +185,6 @@ struct Weight2D { } }; -class SimpleBufferManager; - struct ControlPoints { Vec3f *pos; Vec2f *tex; @@ -200,11 +202,13 @@ struct OutputBuffers { int count; }; -bool CanUseHardwareTessellation(GEPatchPrimType prim); - template void SoftwareTessellation(OutputBuffers &output, const Patch &patch, u32 origVertType, const ControlPoints &points); +} + +bool CanUseHardwareTessellation(GEPatchPrimType prim); + // Define function object for TemplateParameterDispatcher #define TEMPLATE_PARAMETER_DISPATCHER_FUNCTION(NAME, FUNCNAME, FUNCTYPE) \ struct NAME { \ diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 9a90320407..3a37cb63d1 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -702,7 +702,7 @@ TessellationDataTransferD3D11::~TessellationDataTransferD3D11() { } } -void TessellationDataTransferD3D11::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) { +void TessellationDataTransferD3D11::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) { struct TessData { float pos[3]; float pad1; float uv[2]; float pad2[2]; @@ -735,6 +735,8 @@ void TessellationDataTransferD3D11::SendDataToShader(const SimpleVertex *const * context_->Unmap(buf[0], 0); + using Spline::Weight; + // Weights U if (prevSizeWU < weights.size_u) { prevSizeWU = weights.size_u; diff --git a/GPU/D3D11/DrawEngineD3D11.h b/GPU/D3D11/DrawEngineD3D11.h index a29b43553a..11ed3e41e9 100644 --- a/GPU/D3D11/DrawEngineD3D11.h +++ b/GPU/D3D11/DrawEngineD3D11.h @@ -112,7 +112,7 @@ public: TessellationDataTransferD3D11(ID3D11DeviceContext *context, ID3D11Device *device); ~TessellationDataTransferD3D11(); // Send spline/bezier's control points and weights to vertex shader through structured shader buffer. - void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) override; + void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) override; }; // Handles transform, lighting and drawing. diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index 0669412d0a..3dec358faa 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -625,7 +625,7 @@ rotateVBO: GPUDebug::NotifyDraw(); } -void TessellationDataTransferDX9::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) { +void TessellationDataTransferDX9::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) { // TODO } diff --git a/GPU/Directx9/DrawEngineDX9.h b/GPU/Directx9/DrawEngineDX9.h index 7ec653ddef..f1c80eea51 100644 --- a/GPU/Directx9/DrawEngineDX9.h +++ b/GPU/Directx9/DrawEngineDX9.h @@ -101,7 +101,7 @@ class TessellationDataTransferDX9 : public TessellationDataTransfer { public: TessellationDataTransferDX9() {} ~TessellationDataTransferDX9() {} - void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) override; + void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) override; }; // Handles transform, lighting and drawing. diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 79051abb07..937ab0bca8 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -653,7 +653,7 @@ bool DrawEngineGLES::IsCodePtrVertexDecoder(const u8 *ptr) const { return decJitCache_->IsInSpace(ptr); } -void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) { +void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) { bool hasColor = (vertType & GE_VTYPE_COL_MASK) != 0; bool hasTexCoord = (vertType & GE_VTYPE_TC_MASK) != 0; diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index 858f927485..8b29700f83 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -123,7 +123,7 @@ public: EndFrame(); } // Send spline/bezier's control points and weights to vertex shader through floating point texture. - void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) override; + void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) override; void EndFrame(); // Queues textures for deletion. }; diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index a3bba5d3b7..407580e16f 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -1013,7 +1013,7 @@ void DrawEngineVulkan::UpdateUBOs(FrameData *frame) { } } -void TessellationDataTransferVulkan::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) { +void TessellationDataTransferVulkan::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) { // SSBOs that are not simply float1 or float2 need to be padded up to a float4 size. vec3 members // also need to be 16-byte aligned, hence the padding. struct TessData { @@ -1035,6 +1035,8 @@ void TessellationDataTransferVulkan::SendDataToShader(const SimpleVertex *const CopyControlPoints(pos, tex, col, stride, stride, stride, points, size, vertType); + using Spline::Weight; + // Weights U data = (uint8_t *)push_->PushAligned(weights.size_u * sizeof(Weight), (uint32_t *)&bufInfo_[1].offset, &bufInfo_[1].buffer, ssboAlignment); memcpy(data, weights.u, weights.size_u * sizeof(Weight)); diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index c27e9be04b..cece2c08c6 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -123,7 +123,7 @@ public: void SetPushBuffer(VulkanPushBuffer *push) { push_ = push; } // Send spline/bezier's control points and weights to vertex shader through structured shader buffer. - void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) override; + void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) override; const VkDescriptorBufferInfo *GetBufferInfo() { return bufInfo_; } private: VulkanContext *vulkan_; diff --git a/Windows/GEDebugger/VertexPreview.cpp b/Windows/GEDebugger/VertexPreview.cpp index f4e54e76b8..31058e1f8e 100644 --- a/Windows/GEDebugger/VertexPreview.cpp +++ b/Windows/GEDebugger/VertexPreview.cpp @@ -165,6 +165,8 @@ u32 CGEDebugger::PrimPreviewOp() { } static void ExpandBezier(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds) { + using namespace Spline; + 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. @@ -212,6 +214,8 @@ static void ExpandBezier(int &count, int op, const std::vector &si } static void ExpandSpline(int &count, int op, const std::vector &simpleVerts, const std::vector &indices, std::vector &generatedVerts, std::vector &generatedInds) { + using namespace Spline; + 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.