From a418dd05664325157a3eda601b4f0bd2c3adf71e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 30 Aug 2013 10:25:01 +0200 Subject: [PATCH] Spline: Don't create twice the number of triangles we need. --- GPU/GLES/GLES_GPU.cpp | 21 +++++++++++++++++- GPU/GLES/Spline.cpp | 41 ++++++++++++++++++++++++------------ GPU/GLES/TransformPipeline.h | 5 ++++- 3 files changed, 51 insertions(+), 16 deletions(-) diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index 4b4e86ee1f..eb4e3c80dc 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -714,9 +714,29 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { // The arrow and other rotary items in Puzbob are bezier patches, strangely enough. case GE_CMD_BEZIER: { + void *control_points = Memory::GetPointer(gstate_c.vertexAddr); + void *indices = NULL; + if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { + if (!Memory::IsValidAddress(gstate_c.indexAddr)) { + ERROR_LOG_REPORT(G3D, "Bad index address %08x!", gstate_c.indexAddr); + break; + } + indices = Memory::GetPointer(gstate_c.indexAddr); + } + + if (gstate.getPatchPrimitiveType() != GE_PATCHPRIM_TRIANGLES) { + ERROR_LOG_REPORT(G3D, "Unsupported patch primitive %x", gstate.getPatchPrimitiveType()); + break; + } + + // TODO: Get rid of this old horror... int bz_ucount = data & 0xFF; int bz_vcount = (data >> 8) & 0xFF; transformDraw_.DrawBezier(bz_ucount, bz_vcount); + + // And instead use this. + // GEPatchPrimType patchPrim = gstate.getPatchPrimitiveType(); + // transformDraw_.SubmitBezier(control_points, indices, sp_ucount, sp_vcount, patchPrim, gstate.vertType); } break; @@ -1341,7 +1361,6 @@ void GLES_GPU::DoBlockTransfer() { // TODO: Notify all overlapping FBOs that they need to reload. textureCache_.Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT); - // A few games use this INSTEAD of actually drawing the video image to the screen, they just blast it to // the backbuffer. Detect this and have the framebuffermanager draw the pixels. diff --git a/GPU/GLES/Spline.cpp b/GPU/GLES/Spline.cpp index 12dbf58fb5..091568d16a 100644 --- a/GPU/GLES/Spline.cpp +++ b/GPU/GLES/Spline.cpp @@ -77,10 +77,13 @@ void TransformDrawEngine::DrawBezier(int ucount, int vcount) { #define END_OPEN_V 8 // We decode all vertices into a common format for easy interpolation and stuff. -// Not fast but this spline stuff is rarely used for time critical things, strangely enough. +// Not fast but can be optimized later. struct HWSplinePatch { u8 *points[16]; int type; + + // We need to generate both UVs and normals later... + // float u0, v0, u1, v1; }; void CopyTriangle(u8 *&dest, u8 *v1, u8 *v2, u8 * v3, int vertexSize) { @@ -92,8 +95,7 @@ void CopyTriangle(u8 *&dest, u8 *v1, u8 *v2, u8 * v3, int vertexSize) { dest += vertexSize; } -void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertex_type) -{ +void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertex_type) { Flush(); if (prim_type != GE_PATCHPRIM_TRIANGLES) { @@ -102,12 +104,11 @@ void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int } // We're not actually going to decode, only reshuffle. - VertexDecoder vdecoder; - vdecoder.SetVertexType(vertex_type); + VertexDecoder *vdecoder = GetVertexDecoder(vertex_type); - int undecodedVertexSize = vdecoder.VertexSize(); + int undecodedVertexSize = vdecoder->VertexSize(); - const DecVtxFormat& vtxfmt = vdecoder.GetDecVtxFmt(); + const DecVtxFormat& vtxfmt = vdecoder->GetDecVtxFmt(); u16 index_lower_bound = 0; u16 index_upper_bound = count_u * count_v - 1; @@ -133,7 +134,7 @@ void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int else patch.points[point] = (u8 *)control_points + undecodedVertexSize * idx; } - patch.type = (type_u | (type_v<<2)); + patch.type = (type_u | (type_v << 2)); if (patch_u != 0) patch.type &= ~START_OPEN_U; if (patch_v != 0) patch.type &= ~START_OPEN_V; if (patch_u != num_patches_u-1) patch.type &= ~END_OPEN_U; @@ -163,12 +164,10 @@ void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int u8 *v2 = patch.points[point_index+4]; u8 *v3 = patch.points[point_index+5]; - // TODO: Insert UVs where applicable. Actually subdivide. - CopyTriangle(dest, v0, v1, v2, undecodedVertexSize); - CopyTriangle(dest, v2, v1, v0, undecodedVertexSize); - CopyTriangle(dest, v2, v1, v3, undecodedVertexSize); - CopyTriangle(dest, v3, v1, v2, undecodedVertexSize); - count += 12; + // TODO: Insert UVs and normals if not present. + CopyTriangle(dest, v0, v2, v1, undecodedVertexSize); + CopyTriangle(dest, v1, v2, v3, undecodedVertexSize); + count += 6; } } } @@ -179,3 +178,17 @@ void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int SubmitPrim(decoded2, 0, GE_PRIM_TRIANGLES, count, vertTypeWithoutIndex, GE_VTYPE_IDX_NONE, 0); Flush(); } + +// TODO +void TransformDrawEngine::SubmitBezier(void* control_points, void* indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertex_type) { + if (prim_type != GE_PATCHPRIM_TRIANGLES) { + // Only triangles supported! + return; + } + + // We're not actually going to decode, only reshuffle. + VertexDecoder vdecoder; + vdecoder.SetVertexType(vertex_type); + + Flush(); +} diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index 94ab6ef131..306559ab44 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -97,8 +97,11 @@ public: TransformDrawEngine(); virtual ~TransformDrawEngine(); void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertexType, int forceIndexType, int *bytesRead); - void DrawBezier(int ucount, int vcount); void SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertex_type); + void SubmitBezier(void* control_points, void* indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertex_type); + + // legacy + void DrawBezier(int ucount, int vcount); void DecodeVerts(); void SetShaderManager(ShaderManager *shaderManager) {