Merge pull request #8690 from unknownbrackets/spline

Minor spline and bezier accuracy improvements
This commit is contained in:
Henrik Rydgård 2016-04-24 09:33:35 +02:00
commit 259c696a35
5 changed files with 47 additions and 15 deletions

View file

@ -51,7 +51,7 @@ public:
// Same for SubmitPrim
virtual void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) = 0;
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);
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);
std::vector<std::string> DebugGetVertexLoaderIDs();

View file

@ -323,8 +323,13 @@ static void SplinePatchFullQuality(u8 *&dest, u16 *indices, int &count, const Sp
int patch_div_s = (spatch.count_u - 3) * spatch.tess_u;
int patch_div_t = (spatch.count_v - 3) * spatch.tess_v;
if (quality > 1) {
patch_div_s /= quality;
patch_div_t /= quality;
// Don't cut below 2, though.
if (patch_div_s > 2) {
patch_div_s /= quality;
}
if (patch_div_t > 2) {
patch_div_t /= quality;
}
}
// Downsample until it fits, in case crazy tesselation factors are sent.
@ -333,8 +338,8 @@ static void SplinePatchFullQuality(u8 *&dest, u16 *indices, int &count, const Sp
patch_div_t /= 2;
}
if (patch_div_s < 2) patch_div_s = 2;
if (patch_div_t < 2) patch_div_t = 2;
if (patch_div_s < 1) patch_div_s = 1;
if (patch_div_t < 1) patch_div_t = 1;
// First compute all the vertices and put them in an array
SimpleVertex *&vertices = (SimpleVertex*&)dest;
@ -779,14 +784,10 @@ void TesselateBezierPatch(u8 *&dest, u16 *&indices, int &count, int tess_u, int
// This maps GEPatchPrimType to GEPrimitiveType.
const GEPrimitiveType primType[] = { GE_PRIM_TRIANGLES, GE_PRIM_LINES, GE_PRIM_POINTS, GE_PRIM_POINTS };
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) {
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();
// TODO: Verify correct functionality with < 4.
if (count_u < 4 || count_v < 4)
return;
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
@ -797,6 +798,14 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi
if (indices)
GetIndexBounds(indices, count_u * count_v, vertType, &index_lower_bound, &index_upper_bound);
VertexDecoder *origVDecoder = GetVertexDecoder((vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24));
*bytesRead = count_u * count_v * origVDecoder->VertexSize();
// Real hardware seems to draw nothing when given < 4 either U or V.
if (count_u < 4 || count_v < 4) {
return;
}
// Simplify away bones and morph before proceeding
SimpleVertex *simplified_control_points = (SimpleVertex *)(decoded + 65536 * 12);
u8 *temp_buffer = decoded + 65536 * 18;
@ -864,8 +873,8 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi
gstate_c.uv.vOff = 0;
}
int bytesRead;
DispatchSubmitPrim(splineBuffer, quadIndices_, primType[prim_type], count, vertTypeWithIndex16, &bytesRead);
int generatedBytesRead;
DispatchSubmitPrim(splineBuffer, quadIndices_, primType[prim_type], count, vertTypeWithIndex16, &generatedBytesRead);
DispatchFlush();
@ -951,6 +960,14 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi
// We shouldn't really split up into separate 4x4 patches, instead we should do something that works
// like the splines, so we subdivide across the whole "mega-patch".
// If specified as 0, uses 1.
if (tess_u < 1) {
tess_u = 1;
}
if (tess_v < 1) {
tess_v = 1;
}
u16 *inds = quadIndices_;
int maxVertices = SPLINE_BUFFER_SIZE / vertexSize;
for (int patch_idx = 0; patch_idx < num_patches_u*num_patches_v; ++patch_idx) {

View file

@ -921,7 +921,12 @@ void GPU_DX9::Execute_Spline(u32 op, u32 diff) {
bool computeNormals = gstate.isLightingEnabled();
bool patchFacing = gstate.patchfacing & 1;
u32 vertType = gstate.vertType;
drawEngine_.SubmitSpline(control_points, indices, gstate.getPatchDivisionU(), gstate.getPatchDivisionV(), sp_ucount, sp_vcount, sp_utype, sp_vtype, patchPrim, computeNormals, patchFacing, vertType);
int bytesRead = 0;
drawEngine_.SubmitSpline(control_points, indices, gstate.getPatchDivisionU(), gstate.getPatchDivisionV(), sp_ucount, sp_vcount, sp_utype, sp_vtype, patchPrim, computeNormals, patchFacing, vertType, &bytesRead);
// After drawing, we advance pointers - see SubmitPrim which does the same.
int count = sp_ucount * sp_vcount;
AdvanceVerts(gstate.vertType, count, bytesRead);
}
void GPU_DX9::Execute_ViewportType(u32 op, u32 diff) {

View file

@ -1114,7 +1114,12 @@ void GPU_GLES::Execute_Spline(u32 op, u32 diff) {
bool computeNormals = gstate.isLightingEnabled();
bool patchFacing = gstate.patchfacing & 1;
u32 vertType = gstate.vertType;
drawEngine_.SubmitSpline(control_points, indices, gstate.getPatchDivisionU(), gstate.getPatchDivisionV(), sp_ucount, sp_vcount, sp_utype, sp_vtype, patchPrim, computeNormals, patchFacing, vertType);
int bytesRead = 0;
drawEngine_.SubmitSpline(control_points, indices, gstate.getPatchDivisionU(), gstate.getPatchDivisionV(), sp_ucount, sp_vcount, sp_utype, sp_vtype, patchPrim, computeNormals, patchFacing, vertType, &bytesRead);
// After drawing, we advance pointers - see SubmitPrim which does the same.
int count = sp_ucount * sp_vcount;
AdvanceVerts(gstate.vertType, count, bytesRead);
}
void GPU_GLES::Execute_BoundingBox(u32 op, u32 diff) {

View file

@ -971,7 +971,12 @@ void GPU_Vulkan::Execute_Spline(u32 op, u32 diff) {
bool computeNormals = gstate.isLightingEnabled();
bool patchFacing = gstate.patchfacing & 1;
u32 vertType = gstate.vertType;
drawEngine_.SubmitSpline(control_points, indices, gstate.getPatchDivisionU(), gstate.getPatchDivisionV(), sp_ucount, sp_vcount, sp_utype, sp_vtype, patchPrim, computeNormals, patchFacing, vertType);
int bytesRead = 0;
drawEngine_.SubmitSpline(control_points, indices, gstate.getPatchDivisionU(), gstate.getPatchDivisionV(), sp_ucount, sp_vcount, sp_utype, sp_vtype, patchPrim, computeNormals, patchFacing, vertType, &bytesRead);
// After drawing, we advance pointers - see SubmitPrim which does the same.
int count = sp_ucount * sp_vcount;
AdvanceVerts(gstate.vertType, count, bytesRead);
}
void GPU_Vulkan::Execute_BoundingBox(u32 op, u32 diff) {