diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index a417ea9cdc..be4a7cf43a 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -182,6 +182,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) sprintf(stats, "Frames: %i\n" "Draw calls: %i\n" + "Draw flushes: %i\n" "Vertices Transformed: %i\n" "Textures active: %i\n" "Vertex shaders loaded: %i\n" @@ -189,6 +190,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) "Combined shaders loaded: %i\n", gpuStats.numFrames, gpuStats.numDrawCalls, + gpuStats.numFlushes, gpuStats.numVertsTransformed, gpuStats.numTextures, gpuStats.numVertexShaders, diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index d516cfe9e4..54ec9715c0 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -54,6 +54,7 @@ GLES_GPU::GLES_GPU(int renderWidth, int renderHeight) renderHeightFactor_ = (float)renderHeight / 272.0f; shaderManager_ = &shaderManager; TextureCache_Init(); + InitTransform(); // Sanity check gstate if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) { ERROR_LOG(G3D, "gstate has drifted out of sync!"); @@ -113,6 +114,7 @@ void GLES_GPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, int format) void GLES_GPU::CopyDisplayToOutput() { + Flush(); if (!g_Config.bBufferedRendering) return; diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 690088e98e..439157c9b9 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -22,11 +22,11 @@ #include "../GPUInterface.h" #include "Framebuffer.h" +#include "VertexDecoder.h" #include "gfx_es2/fbo.h" class ShaderManager; class LinkedShader; -struct DecVtxFormat; class GLES_GPU : public GPUInterface { @@ -52,10 +52,11 @@ public: private: // TransformPipeline.cpp + void InitTransform(); void TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead = 0); //void SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexType, int vertexCount, void *inds, const DecVtxFormat &decVtxFormat, int indexLowerBound, int indexUpperBound, float *customUV); void ApplyDrawState(); - void Flush(int prim); + void Flush(); void UpdateViewportAndProjection(); void DrawBezier(int ucount, int vcount); void DoBlockTransfer(); diff --git a/GPU/GLES/IndexGenerator.cpp b/GPU/GLES/IndexGenerator.cpp index b08ab3cd5b..d28d92d663 100644 --- a/GPU/GLES/IndexGenerator.cpp +++ b/GPU/GLES/IndexGenerator.cpp @@ -25,13 +25,14 @@ const u8 indexedPrimitiveType[7] = { GE_PRIM_TRIANGLES, GE_PRIM_TRIANGLES, GE_PRIM_TRIANGLES, - GE_PRIM_TRIANGLES, + GE_PRIM_RECTANGLES, }; void IndexGenerator::Reset() { prim_ = -1; - inds_ = 0; count_ = 0; + index_ = 0; + this->inds_ = indsBase_; } bool IndexGenerator::PrimCompatible(int prim) { @@ -40,12 +41,10 @@ bool IndexGenerator::PrimCompatible(int prim) { return indexedPrimitiveType[prim] == indexedPrimitiveType[prim_]; } -void IndexGenerator::Start(u16 *inds, int baseIndex, int prim) +void IndexGenerator::Setup(u16 *inds) { - count_ = 0; - this->inds_ = inds; - index_ = baseIndex; - prim_ = indexedPrimitiveType[prim]; + this->indsBase_ = inds; + Reset(); } void IndexGenerator::AddPoints(int numVerts) @@ -58,6 +57,7 @@ void IndexGenerator::AddPoints(int numVerts) // ignore overflow verts index_ += numVerts; count_ += numVerts; + prim_ = GE_PRIM_POINTS; } void IndexGenerator::AddList(int numVerts) @@ -74,6 +74,7 @@ void IndexGenerator::AddList(int numVerts) // ignore overflow verts index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::AddStrip(int numVerts) @@ -89,6 +90,7 @@ void IndexGenerator::AddStrip(int numVerts) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::AddFan(int numVerts) @@ -102,6 +104,7 @@ void IndexGenerator::AddFan(int numVerts) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::TranslatePoints(int numVerts, const u8 *inds, int offset) @@ -112,6 +115,7 @@ void IndexGenerator::TranslatePoints(int numVerts, const u8 *inds, int offset) } index_ += numVerts; count_ += numVerts; + prim_ = GE_PRIM_POINTS; } void IndexGenerator::TranslatePoints(int numVerts, const u16 *inds, int offset) @@ -122,6 +126,7 @@ void IndexGenerator::TranslatePoints(int numVerts, const u16 *inds, int offset) } index_ += numVerts; count_ += numVerts; + prim_ = GE_PRIM_POINTS; } void IndexGenerator::TranslateList(int numVerts, const u8 *inds, int offset) @@ -135,6 +140,7 @@ void IndexGenerator::TranslateList(int numVerts, const u8 *inds, int offset) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::TranslateStrip(int numVerts, const u8 *inds, int offset) @@ -150,6 +156,7 @@ void IndexGenerator::TranslateStrip(int numVerts, const u8 *inds, int offset) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::TranslateFan(int numVerts, const u8 *inds, int offset) @@ -164,6 +171,7 @@ void IndexGenerator::TranslateFan(int numVerts, const u8 *inds, int offset) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::TranslateList(int numVerts, const u16 *inds, int offset) @@ -177,6 +185,7 @@ void IndexGenerator::TranslateList(int numVerts, const u16 *inds, int offset) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::TranslateStrip(int numVerts, const u16 *inds, int offset) @@ -192,6 +201,7 @@ void IndexGenerator::TranslateStrip(int numVerts, const u16 *inds, int offset) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::TranslateFan(int numVerts, const u16 *inds, int offset) @@ -206,6 +216,7 @@ void IndexGenerator::TranslateFan(int numVerts, const u16 *inds, int offset) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } //Lines @@ -219,6 +230,7 @@ void IndexGenerator::AddLineList(int numVerts) } index_ += numVerts; count_ += numLines * 2; + prim_ = GE_PRIM_LINES; } void IndexGenerator::AddLineStrip(int numVerts) @@ -231,6 +243,20 @@ void IndexGenerator::AddLineStrip(int numVerts) } index_ += numVerts; count_ += numLines * 2; + prim_ = GE_PRIM_LINES; +} + +void IndexGenerator::AddRectangles(int numVerts) +{ + int numRects = numVerts / 2; + for (int i = 0; i < numRects; i++) + { + *inds_++ = index_ + i*2; + *inds_++ = index_ + i*2+1; + } + index_ += numVerts; + count_ += numRects * 2; + prim_ = GE_PRIM_RECTANGLES; } void IndexGenerator::TranslateLineList(int numVerts, const u8 *inds, int offset) @@ -243,6 +269,7 @@ void IndexGenerator::TranslateLineList(int numVerts, const u8 *inds, int offset) } index_ += numVerts; count_ += numLines * 2; + prim_ = GE_PRIM_LINES; } void IndexGenerator::TranslateLineStrip(int numVerts, const u8 *inds, int offset) @@ -255,6 +282,7 @@ void IndexGenerator::TranslateLineStrip(int numVerts, const u8 *inds, int offset } index_ += numVerts; count_ += numLines * 2; + prim_ = GE_PRIM_LINES; } void IndexGenerator::TranslateLineList(int numVerts, const u16 *inds, int offset) @@ -267,6 +295,7 @@ void IndexGenerator::TranslateLineList(int numVerts, const u16 *inds, int offset } index_ += numVerts; count_ += numLines * 2; + prim_ = GE_PRIM_LINES; } void IndexGenerator::TranslateLineStrip(int numVerts, const u16 *inds, int offset) @@ -279,4 +308,31 @@ void IndexGenerator::TranslateLineStrip(int numVerts, const u16 *inds, int offse } index_ += numVerts; count_ += numLines * 2; -} \ No newline at end of file + prim_ = GE_PRIM_LINES; +} + +void IndexGenerator::TranslateRectangles(int numVerts, const u8 *inds, int offset) +{ + int numRects = numVerts / 2; + for (int i = 0; i < numRects; i++) + { + *inds_++ = index_ + i*2; + *inds_++ = index_ + i*2+1; + } + index_ += numVerts; + count_ += numRects * 2; + prim_ = GE_PRIM_RECTANGLES; +} + +void IndexGenerator::TranslateRectangles(int numVerts, const u16 *inds, int offset) +{ + int numRects = numVerts / 2; + for (int i = 0; i < numRects; i++) + { + *inds_++ = index_ + i*2; + *inds_++ = index_ + i*2+1; + } + index_ += numVerts; + count_ += numRects * 2; + prim_ = GE_PRIM_RECTANGLES; +} diff --git a/GPU/GLES/IndexGenerator.h b/GPU/GLES/IndexGenerator.h index bb2a9bde00..af6da67ae4 100644 --- a/GPU/GLES/IndexGenerator.h +++ b/GPU/GLES/IndexGenerator.h @@ -24,9 +24,10 @@ class IndexGenerator { public: + void Setup(u16 *indexptr); void Reset(); - void Start(u16 *indexptr, int baseIndex, int prim); bool PrimCompatible(int prim); + int Prim() const { return prim_; } // Points (why index these? code simplicity) void AddPoints(int numVerts); @@ -37,15 +38,21 @@ public: // Lines void AddLineList(int numVerts); void AddLineStrip(int numVerts); + // Rectangles + void AddRectangles(int numVerts); void TranslatePoints(int numVerts, const u8 *inds, int offset); void TranslatePoints(int numVerts, const u16 *inds, int offset); // Translates already indexed lists void TranslateLineList(int numVerts, const u8 *inds, int offset); - void TranslateLineStrip(int numVerts, const u8 *inds, int offset); void TranslateLineList(int numVerts, const u16 *inds, int offset); + void TranslateLineStrip(int numVerts, const u8 *inds, int offset); void TranslateLineStrip(int numVerts, const u16 *inds, int offset); + void TranslateRectangles(int numVerts, const u8 *inds, int offset); + void TranslateRectangles(int numVerts, const u16 *inds, int offset); + + void TranslateList(int numVerts, const u8 *inds, int offset); void TranslateStrip(int numVerts, const u8 *inds, int offset); void TranslateFan(int numVerts, const u8 *inds, int offset); @@ -56,7 +63,10 @@ public: int MaxIndex() { return index_; } int VertexCount() { return count_; } + bool Empty() { return index_ == 0; } + private: + u16 *indsBase_; u16 *inds_; int index_; int count_; diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 913f2c23ca..88d08908cb 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -43,7 +43,10 @@ const GLuint glprim[8] = { }; u8 decoded[65536 * 32]; +VertexDecoder dec; uint16_t decIndex[65536]; // Unused +int numVerts; +int numInds; IndexGenerator indexGen; @@ -265,7 +268,7 @@ static void DesetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decF // Actually again, single quads could be drawn more efficiently using GL_TRIANGLE_STRIP, no need to duplicate verts as for // GL_TRIANGLES. Still need to sw transform to compute the extra two corners though. -void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex, float *customUV) +void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex) { /* DEBUG_LOG(G3D, "View matrix:"); @@ -418,10 +421,7 @@ void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, } } - if (customUV) { - uv[0] = customUV[index * 2 + 0]*gstate_c.uScale + gstate_c.uOff; - uv[1] = customUV[index * 2 + 1]*gstate_c.vScale + gstate_c.vOff; - } else if (reader.hasUV()) { + if (reader.hasUV()) { float ruv[2]; reader.ReadUV(ruv); // Perform texture coordinate generation after the transform and lighting - one style of UV depends on lights. @@ -575,22 +575,27 @@ void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, if (program->a_color1 != -1) glDisableVertexAttribArray(program->a_color1); } +void GLES_GPU::InitTransform() { + indexGen.Setup(decIndex); +} + void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead) { // For the future if (!indexGen.PrimCompatible(prim)) - Flush(prim); + Flush(); + + gpuStats.numDrawCalls++; + gpuStats.numVertsTransformed += vertexCount; int indexLowerBound, indexUpperBound; // First, decode the verts and apply morphing - VertexDecoder dec; dec.SetVertexType(gstate.vertType); dec.DecodeVerts(decoded, verts, inds, prim, vertexCount, &indexLowerBound, &indexUpperBound); + if (bytesRead) *bytesRead = vertexCount * dec.VertexSize(); - indexGen.Start(decIndex, 0, prim); - int indexType = (gstate.vertType & GE_VTYPE_IDX_MASK); if (forceIndexType != -1) indexType = forceIndexType; switch (indexType) { @@ -602,7 +607,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte case GE_PRIM_TRIANGLES: indexGen.AddList(vertexCount); break; case GE_PRIM_TRIANGLE_STRIP: indexGen.AddStrip(vertexCount); break; case GE_PRIM_TRIANGLE_FAN: indexGen.AddFan(vertexCount); break; - case GE_PRIM_RECTANGLES: indexGen.AddLineList(vertexCount); break; // Same + case GE_PRIM_RECTANGLES: indexGen.AddRectangles(vertexCount); break; // Same } break; @@ -614,7 +619,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte case GE_PRIM_TRIANGLES: indexGen.TranslateList(vertexCount, (const u8 *)inds, -indexLowerBound); break; case GE_PRIM_TRIANGLE_STRIP: indexGen.TranslateStrip(vertexCount, (const u8 *)inds, -indexLowerBound); break; case GE_PRIM_TRIANGLE_FAN: indexGen.TranslateFan(vertexCount, (const u8 *)inds, -indexLowerBound); break; - case GE_PRIM_RECTANGLES: indexGen.TranslateLineList(vertexCount, (const u8 *)inds, -indexLowerBound); break; // Same + case GE_PRIM_RECTANGLES: indexGen.TranslateRectangles(vertexCount, (const u8 *)inds, -indexLowerBound); break; // Same } break; @@ -626,12 +631,18 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte case GE_PRIM_TRIANGLES: indexGen.TranslateList(vertexCount, (const u16 *)inds, -indexLowerBound); break; case GE_PRIM_TRIANGLE_STRIP: indexGen.TranslateStrip(vertexCount, (const u16 *)inds, -indexLowerBound); break; case GE_PRIM_TRIANGLE_FAN: indexGen.TranslateFan(vertexCount, (const u16 *)inds, -indexLowerBound); break; - case GE_PRIM_RECTANGLES: indexGen.TranslateLineList(vertexCount, (const u16 *)inds, -indexLowerBound); break; // Same + case GE_PRIM_RECTANGLES: indexGen.TranslateRectangles(vertexCount, (const u16 *)inds, -indexLowerBound); break; // Same } break; } - indexType = GE_VTYPE_IDX_16BIT; + Flush(); +} + +void GLES_GPU::Flush() +{ + if (indexGen.Empty()) + return; // From here on out, the index type is ALWAYS 16-bit. Deal with it. // And here we should return, having collected the morphed but untransformed vertices. @@ -654,12 +665,13 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte } gstate_c.textureChanged = false; } - gpuStats.numDrawCalls++; - gpuStats.numVertsTransformed += vertexCount; + gpuStats.numFlushes++; // TODO: This should not be done on every drawcall, we should collect vertex data // until critical state changes. That's when we draw (flush). + int prim = indexGen.Prim(); + ApplyDrawState(); UpdateViewportAndProjection(); @@ -670,11 +682,9 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte glDrawElements(glprim[prim], indexGen.VertexCount(), GL_UNSIGNED_SHORT, (GLvoid *)decIndex); DesetupDecFmtForDraw(program, dec.GetDecVtxFmt()); } else { - SoftwareTransformAndDraw(prim, program, indexGen.VertexCount(), (void *)decIndex, indexType, dec.GetDecVtxFmt(), - indexGen.MaxIndex(), customUV); + SoftwareTransformAndDraw(prim, program, indexGen.VertexCount(), (void *)decIndex, GE_VTYPE_IDX_16BIT, dec.GetDecVtxFmt(), + indexGen.MaxIndex()); } -} -void GLES_GPU::Flush(int prim) { - // TODO -} + indexGen.Reset(); +} \ No newline at end of file diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 66cb21d90b..e031f6bc71 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -263,6 +263,7 @@ struct GPUStatistics // Per frame statistics int numDrawCalls; + int numFlushes; int numVertsTransformed; int numTextureSwitches; int numShaderSwitches;