diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index d7b6932672..1d0218e5a1 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -255,9 +255,13 @@ VertexDecoder *TransformDrawEngine::GetVertexDecoder(u32 vtype) { } void TransformDrawEngine::SetupVertexDecoder(u32 vertType) { + SetupVertexDecoderInternal(vertType); +} + +inline void TransformDrawEngine::SetupVertexDecoderInternal(u32 vertType) { // As the decoder depends on the UVGenMode when we use UV prescale, we simply mash it // into the top of the verttype where there are unused bits. - u32 vertTypeID = (vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24); + const u32 vertTypeID = (vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24); // If vtype has changed, setup the vertex decoder. // TODO: Simply cache the setup decoders instead. @@ -280,7 +284,7 @@ void TransformDrawEngine::SubmitPrim(void *verts, void *inds, GEPrimitiveType pr } prevPrim_ = prim; - SetupVertexDecoder(vertType); + SetupVertexDecoderInternal(vertType); dec_->IncrementStat(STAT_VERTSSUBMITTED, vertexCount); @@ -373,33 +377,45 @@ void TransformDrawEngine::DecodeVertsStep() { // 1. Look ahead to find the max index, only looking as "matching" drawcalls. // Expand the lower and upper bounds as we go. - int j = i + 1; int lastMatch = i; - while (j < numDrawCalls) { - if (drawCalls[j].verts != dc.verts) - break; - if (uvScale && memcmp(&uvScale[j], &uvScale[i], sizeof(uvScale[0])) != 0) - break; + const int total = numDrawCalls; + if (uvScale) { + for (int j = i + 1; j < total; ++j) { + if (drawCalls[j].verts != dc.verts) + break; + if (memcmp(&uvScale[j], &uvScale[i], sizeof(uvScale[0])) != 0) + break; - indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound); - indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound); - lastMatch = j; - j++; - } + indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound); + indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound); + lastMatch = j; + } + } else { + for (int j = i + 1; j < total; ++j) { + if (drawCalls[j].verts != dc.verts) + break; - // 2. Loop through the drawcalls, translating indices as we go. - for (j = i; j <= lastMatch; j++) { - switch (indexType) { - case GE_VTYPE_IDX_8BIT >> GE_VTYPE_IDX_SHIFT: - indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u8 *)drawCalls[j].inds, indexLowerBound); - break; - case GE_VTYPE_IDX_16BIT >> GE_VTYPE_IDX_SHIFT: - indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u16 *)drawCalls[j].inds, indexLowerBound); - break; + indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound); + indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound); + lastMatch = j; } } - int vertexCount = indexUpperBound - indexLowerBound + 1; + // 2. Loop through the drawcalls, translating indices as we go. + switch (indexType) { + case GE_VTYPE_IDX_8BIT >> GE_VTYPE_IDX_SHIFT: + for (int j = i; j <= lastMatch; j++) { + indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u8 *)drawCalls[j].inds, indexLowerBound); + } + break; + case GE_VTYPE_IDX_16BIT >> GE_VTYPE_IDX_SHIFT: + for (int j = i; j <= lastMatch; j++) { + indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u16 *)drawCalls[j].inds, indexLowerBound); + } + break; + } + + const int vertexCount = indexUpperBound - indexLowerBound + 1; // 3. Decode that range of vertex data. dec_->DecodeVerts(decoded + decodedVerts_ * (int)dec_->GetDecVtxFmt().stride, dc.verts, indexLowerBound, indexUpperBound); diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index c0c146cbda..4176168890 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -124,6 +124,7 @@ public: void ClearTrackedVertexArrays(); void SetupVertexDecoder(u32 vertType); + inline void SetupVertexDecoderInternal(u32 vertType); // This requires a SetupVertexDecoder call first. int EstimatePerVertexCost() { diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 679b6fa37e..5fab34bdb8 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -559,17 +559,19 @@ void GPUCommon::SlowRunLoop(DisplayList &list) // The newPC parameter is used for jumps, we don't count cycles between. void GPUCommon::UpdatePC(u32 currentPC, u32 newPC) { // Rough estimate, 2 CPU ticks (it's double the clock rate) per GPU instruction. - int executed = (currentPC - cycleLastPC) / 4; + u32 executed = (currentPC - cycleLastPC) / 4; cyclesExecuted += 2 * executed; - gpuStats.otherGPUCycles += 2 * executed; - cycleLastPC = newPC == 0 ? currentPC : newPC; + cycleLastPC = currentPC; - gpuStats.gpuCommandsAtCallLevel[std::min(currentList->stackptr, 3)] += executed; + if (g_Config.bShowDebugStats) { + gpuStats.otherGPUCycles += 2 * executed; + gpuStats.gpuCommandsAtCallLevel[std::min(currentList->stackptr, 3)] += executed; + } // Exit the runloop and recalculate things. This happens a lot in some games. easy_guard innerGuard(listLock); if (currentList) - downcount = currentList->stall == 0 ? 0x0FFFFFFF : (currentList->stall - cycleLastPC) / 4; + downcount = currentList->stall == 0 ? 0x0FFFFFFF : (currentList->stall - currentPC) / 4; else downcount = 0; } diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 6f53879939..c25e98e8db 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -81,7 +81,10 @@ protected: // To avoid virtual calls to PreExecuteOp(). virtual void FastRunLoop(DisplayList &list) = 0; void SlowRunLoop(DisplayList &list); - void UpdatePC(u32 currentPC, u32 newPC = 0); + void UpdatePC(u32 currentPC, u32 newPC); + void UpdatePC(u32 currentPC) { + UpdatePC(currentPC, currentPC); + } void UpdateState(GPUState state); void PopDLQueue(); void CheckDrawSync();