Skip to content

Commit

Permalink
[spline/bezier]Put the output buffers all in one structure.
Browse files Browse the repository at this point in the history
  • Loading branch information
xebra committed Oct 7, 2018
1 parent a241058 commit c4a8d80
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 22 deletions.
47 changes: 25 additions & 22 deletions GPU/Common/SplineCommon.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ class SubdivisionSurface {
} }


template <bool sampleNrm, bool sampleCol, bool sampleTex, bool useSSE4, bool patchFacing> template <bool sampleNrm, bool sampleCol, bool sampleTex, bool useSSE4, bool patchFacing>
void Tessellate(SimpleVertex *vertices, u16 *indices, int &count) { void Tessellate(OutputBuffers &output) {
const float inv_u = 1.0f / (float)patch.tess_u; const float inv_u = 1.0f / (float)patch.tess_u;
const float inv_v = 1.0f / (float)patch.tess_v; const float inv_v = 1.0f / (float)patch.tess_v;


Expand Down Expand Up @@ -375,7 +375,7 @@ class SubdivisionSurface {
const int index_v = patch.GetIndexV(patch_v, tile_v); const int index_v = patch.GetIndexV(patch_v, tile_v);
const Weight &wv = weights.v[index_v]; const Weight &wv = weights.v[index_v];


SimpleVertex &vert = vertices[patch.GetIndex(index_u, index_v, patch_u, patch_v)]; SimpleVertex &vert = output.vertices[patch.GetIndex(index_u, index_v, patch_u, patch_v)];


// Tessellate // Tessellate
vert.pos = tess_pos.SampleV(wv.basis); vert.pos = tess_pos.SampleV(wv.basis);
Expand Down Expand Up @@ -406,13 +406,13 @@ class SubdivisionSurface {
} }
} }


patch.BuildIndex(indices, count); patch.BuildIndex(output.indices, output.count);
} }


TEMPLATE_PARAMETER_DISPATCHER_FUNCTION(Tess, SubdivisionSurface::Tessellate); TEMPLATE_PARAMETER_DISPATCHER_FUNCTION(Tess, SubdivisionSurface::Tessellate);


void Tessellate(SimpleVertex *vertices, u16 *indices, int &count, u32 origVertType) { void Tessellate(OutputBuffers &output, u32 origVertType) {
using TessFunc = void(SubdivisionSurface::*)(SimpleVertex *, u16 *, int &); using TessFunc = void(SubdivisionSurface::*)(OutputBuffers &);
constexpr int NumParams = 5; constexpr int NumParams = 5;
static TemplateParameterDispatcher<TessFunc, NumParams, Tess> dispatcher; // Initialize only once static TemplateParameterDispatcher<TessFunc, NumParams, Tess> dispatcher; // Initialize only once


Expand All @@ -424,23 +424,23 @@ class SubdivisionSurface {
patch.patchFacing, patch.patchFacing,
}; };
TessFunc func = dispatcher.GetFunc(params); TessFunc func = dispatcher.GetFunc(params);
(this->*func)(vertices, indices, count); (this->*func)(output);
} }
}; };


template<class Patch, class Cache> template<class Patch, class Cache>
static void SoftwareTessellation(SimpleVertex *vertices, u16 *indices, int &count, const Patch &patch, u32 origVertType, static void SoftwareTessellation(OutputBuffers &output, const Patch &patch, u32 origVertType,
const SimpleVertex *const *points, SimpleBufferManager &managedBuf, Cache &weightsCache) { const SimpleVertex *const *points, SimpleBufferManager &managedBuf, Cache &weightsCache) {
u32 key_u = weightsCache.ToKey(patch.tess_u, patch.count_u, patch.type_u); u32 key_u = weightsCache.ToKey(patch.tess_u, patch.count_u, patch.type_u);
u32 key_v = weightsCache.ToKey(patch.tess_v, patch.count_v, patch.type_v); u32 key_v = weightsCache.ToKey(patch.tess_v, patch.count_v, patch.type_v);
Weight2D weights(weightsCache, key_u, key_v); Weight2D weights(weightsCache, key_u, key_v);


SubdivisionSurface<Patch> surface(managedBuf, points, patch, weights); SubdivisionSurface<Patch> surface(managedBuf, points, patch, weights);
surface.Tessellate(vertices, indices, count, origVertType); surface.Tessellate(output, origVertType);
} }


template<class Patch, class Cache> template<class Patch, class Cache>
static void HardwareTessellation(SimpleVertex *vertices, u16 *indices, int &count, const Patch &patch, u32 origVertType, static void HardwareTessellation(OutputBuffers &output, const Patch &patch, u32 origVertType,
const SimpleVertex *const *points, Cache &weightsCache, TessellationDataTransfer *tessDataTransfer) { const SimpleVertex *const *points, Cache &weightsCache, TessellationDataTransfer *tessDataTransfer) {
u32 key_u = weightsCache.ToKey(patch.tess_u, patch.count_u, patch.type_u); u32 key_u = weightsCache.ToKey(patch.tess_u, patch.count_u, patch.type_u);
u32 key_v = weightsCache.ToKey(patch.tess_v, patch.count_v, patch.type_v); u32 key_v = weightsCache.ToKey(patch.tess_v, patch.count_v, patch.type_v);
Expand All @@ -454,15 +454,15 @@ static void HardwareTessellation(SimpleVertex *vertices, u16 *indices, int &coun
float inv_v = 1.0f / (float)patch.tess_v; float inv_v = 1.0f / (float)patch.tess_v;
for (int tile_v = 0; tile_v <= patch.tess_v; ++tile_v) { for (int tile_v = 0; tile_v <= patch.tess_v; ++tile_v) {
for (int tile_u = 0; tile_u <= patch.tess_u; ++tile_u) { for (int tile_u = 0; tile_u <= patch.tess_u; ++tile_u) {
SimpleVertex &vert = vertices[tile_v * (patch.tess_u + 1) + tile_u]; SimpleVertex &vert = output.vertices[tile_v * (patch.tess_u + 1) + tile_u];
vert.pos.x = (float)tile_u; vert.pos.x = (float)tile_u;
vert.pos.y = (float)tile_v; vert.pos.y = (float)tile_v;
// For texcoord generation // For texcoord generation
vert.nrm.x = (float)tile_u * inv_u; vert.nrm.x = (float)tile_u * inv_u;
vert.nrm.y = (float)tile_v * inv_v; vert.nrm.y = (float)tile_v * inv_v;
} }
} }
BuildIndex(indices, count, patch.tess_u, patch.tess_v, patch.primType); BuildIndex(output.indices, output.count, patch.tess_u, patch.tess_v, patch.primType);
} }


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) { 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) {
Expand Down Expand Up @@ -507,8 +507,10 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi
for (int idx = 0; idx < count_u * count_v; idx++) for (int idx = 0; idx < count_u * count_v; idx++)
points[idx] = simplified_control_points + (indices ? ConvertIndex(idx) : idx); points[idx] = simplified_control_points + (indices ? ConvertIndex(idx) : idx);


int count = 0; OutputBuffers output;
u8 *dest = splineBuffer; output.vertices = (SimpleVertex *)splineBuffer;
output.indices = quadIndices_;
output.count = 0;


SplinePatchLocal patch; SplinePatchLocal patch;
patch.tess_u = tess_u; patch.tess_u = tess_u;
Expand All @@ -523,11 +525,11 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi
patch.patchFacing = patchFacing; patch.patchFacing = patchFacing;


if (CanUseHardwareTessellation(prim_type)) { if (CanUseHardwareTessellation(prim_type)) {
HardwareTessellation((SimpleVertex *)splineBuffer, quadIndices_, count, patch, origVertType, points, splineWeightsCache, tessDataTransfer); HardwareTessellation(output, patch, origVertType, points, splineWeightsCache, tessDataTransfer);
numPatches = patch.num_patches_u * patch.num_patches_v; numPatches = patch.num_patches_u * patch.num_patches_v;
} else { } else {
patch.Init(SPLINE_BUFFER_SIZE / vertexSize); patch.Init(SPLINE_BUFFER_SIZE / vertexSize);
SoftwareTessellation((SimpleVertex *)splineBuffer, quadIndices_, count, patch, origVertType, points, managedBuf, splineWeightsCache); SoftwareTessellation(output, patch, origVertType, points, managedBuf, splineWeightsCache);
} }


u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT; u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
Expand All @@ -545,7 +547,7 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi
uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode()); uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode());


int generatedBytesRead; int generatedBytesRead;
DispatchSubmitPrim(splineBuffer, quadIndices_, PatchPrimToPrim(prim_type), count, vertTypeID, &generatedBytesRead); DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(prim_type), output.count, vertTypeID, &generatedBytesRead);


DispatchFlush(); DispatchFlush();


Expand Down Expand Up @@ -598,9 +600,10 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi
for (int idx = 0; idx < count_u * count_v; idx++) for (int idx = 0; idx < count_u * count_v; idx++)
points[idx] = simplified_control_points + (indices ? ConvertIndex(idx) : idx); points[idx] = simplified_control_points + (indices ? ConvertIndex(idx) : idx);


int count = 0; OutputBuffers output;
u8 *dest = splineBuffer; output.vertices = (SimpleVertex *)splineBuffer;
u16 *inds = quadIndices_; output.indices = quadIndices_;
output.count = 0;


BezierPatch patch; BezierPatch patch;
patch.tess_u = tess_u; patch.tess_u = tess_u;
Expand All @@ -613,11 +616,11 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi
patch.patchFacing = patchFacing; patch.patchFacing = patchFacing;


if (CanUseHardwareTessellation(prim_type)) { if (CanUseHardwareTessellation(prim_type)) {
HardwareTessellation((SimpleVertex *)splineBuffer, quadIndices_, count, patch, origVertType, points, bezierWeightsCache, tessDataTransfer); HardwareTessellation(output, patch, origVertType, points, bezierWeightsCache, tessDataTransfer);
numPatches = patch.num_patches_u * patch.num_patches_v; numPatches = patch.num_patches_u * patch.num_patches_v;
} else { } else {
patch.Init(SPLINE_BUFFER_SIZE / vertexSize); patch.Init(SPLINE_BUFFER_SIZE / vertexSize);
SoftwareTessellation((SimpleVertex *)splineBuffer, quadIndices_, count, patch, origVertType, points, managedBuf, bezierWeightsCache); SoftwareTessellation(output, patch, origVertType, points, managedBuf, bezierWeightsCache);
} }


u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT; u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
Expand All @@ -634,7 +637,7 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi


uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode()); uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode());
int generatedBytesRead; int generatedBytesRead;
DispatchSubmitPrim(splineBuffer, quadIndices_, PatchPrimToPrim(prim_type), count, vertTypeID, &generatedBytesRead); DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(prim_type), output.count, vertTypeID, &generatedBytesRead);


DispatchFlush(); DispatchFlush();


Expand Down
6 changes: 6 additions & 0 deletions GPU/Common/SplineCommon.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ struct Weight2D {
} }
}; };


struct OutputBuffers {
SimpleVertex *vertices;
u16 *indices;
int count;
};

bool CanUseHardwareTessellation(GEPatchPrimType prim); bool CanUseHardwareTessellation(GEPatchPrimType prim);
void TessellateSplinePatch(u8 *&dest, u16 *indices, int &count, SplinePatchLocal &spatch, u32 origVertType, int maxVertices); 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); void TessellateBezierPatch(u8 *&dest, u16 *&indices, int &count, int tess_u, int tess_v, const BezierPatch &patch, u32 origVertType, int maxVertices);
Expand Down

0 comments on commit c4a8d80

Please sign in to comment.