mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #11560 from xebra/refactor_spline_bezier
[spline/bezier]Unify SubmitSpline/Bezier.
This commit is contained in:
commit
79d16f7b9f
4 changed files with 73 additions and 148 deletions
|
@ -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<class Surface>
|
||||
void SubmitCurve(const void *control_points, const void *indices, Surface &surface, u32 vertType, int *bytesRead, const char *scope);
|
||||
void ClearSplineBezierWeights();
|
||||
|
||||
std::vector<std::string> DebugGetVertexLoaderIDs();
|
||||
|
|
|
@ -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<BezierSurface>(const void *control_points, const void *indices, BezierSurface &surface, u32 vertType, int *bytesRead, const char *scope);
|
||||
template void DrawEngineCommon::SubmitCurve<SplineSurface>(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<class Surface>
|
||||
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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue