Spline: Don't create twice the number of triangles we need.

This commit is contained in:
Henrik Rydgard 2013-08-30 10:25:01 +02:00
parent 9fecfe434f
commit a418dd0566
3 changed files with 51 additions and 16 deletions

View File

@ -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.

View File

@ -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();
}

View File

@ -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) {