Merge pull request #5808 from unknownbrackets/perf

More small performance tweaks based on ARM profiling
This commit is contained in:
Henrik Rydgård committed 2014-04-05 22:01:23 +02:00
commit 4931cd131f
4 files changed
+51 -29

No files matched your search

+39 -23
View File
@@ -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);
+1
View File
@@ -124,6 +124,7 @@ public:
void ClearTrackedVertexArrays();
void SetupVertexDecoder(u32 vertType);
inline void SetupVertexDecoderInternal(u32 vertType);
// This requires a SetupVertexDecoder call first.
int EstimatePerVertexCost() {
+7 -5
View File
@@ -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;
}
+4 -1
View File
@@ -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();