Don't hash vertex buffers every frame (TCP-style backoff up until every 16th)

Saves quite a bit time otherwise spent in CityHash, blowing the dcache every time.
This commit is contained in:
Henrik Rydgard 2013-02-06 00:42:06 +01:00
parent 0f5317d65d
commit 0ca279e81d
2 changed files with 30 additions and 18 deletions

View File

@ -819,6 +819,7 @@ u32 TransformDrawEngine::ComputeHash() {
u32 fullhash = 0; u32 fullhash = 0;
int vertexSize = dec.GetDecVtxFmt().stride; int vertexSize = dec.GetDecVtxFmt().stride;
// TODO: Add some caps both for numDrawCalls and num verts to check?
for (int i = 0; i < numDrawCalls; i++) { for (int i = 0; i < numDrawCalls; i++) {
if (!drawCalls[i].inds) { if (!drawCalls[i].inds) {
fullhash += CityHash32((const char *)drawCalls[i].verts, vertexSize * drawCalls[i].vertexCount); fullhash += CityHash32((const char *)drawCalls[i].verts, vertexSize * drawCalls[i].vertexCount);
@ -920,6 +921,7 @@ void TransformDrawEngine::Flush() {
u32 dataHash = ComputeHash(); u32 dataHash = ComputeHash();
vai->hash = dataHash; vai->hash = dataHash;
vai->status = VertexArrayInfo::VAI_HASHING; vai->status = VertexArrayInfo::VAI_HASHING;
vai->drawsUntilNextFullHash = 0;
DecodeVerts(); // writes to indexGen DecodeVerts(); // writes to indexGen
goto rotateVBO; goto rotateVBO;
} }
@ -928,27 +930,33 @@ void TransformDrawEngine::Flush() {
// But if we get this far it's likely to be worth creating a vertex buffer. // But if we get this far it's likely to be worth creating a vertex buffer.
case VertexArrayInfo::VAI_HASHING: case VertexArrayInfo::VAI_HASHING:
{ {
u32 newHash = ComputeHash();
vai->numDraws++; vai->numDraws++;
// TODO: tweak if (vai->drawsUntilNextFullHash == 0) {
if (vai->numDraws > 100000) { u32 newHash = ComputeHash();
vai->status = VertexArrayInfo::VAI_RELIABLE; // exponential backoff up to 16 frames
} vai->drawsUntilNextFullHash = std::min(16, vai->numDraws);
if (newHash == vai->hash) { // TODO: tweak
gpuStats.numCachedDrawCalls++; if (vai->numDraws > 1000) {
vai->status = VertexArrayInfo::VAI_RELIABLE;
}
if (newHash != vai->hash) {
vai->status = VertexArrayInfo::VAI_UNRELIABLE;
if (vai->vbo) {
glDeleteBuffers(1, &vai->vbo);
vai->vbo = 0;
}
if (vai->ebo) {
glDeleteBuffers(1, &vai->ebo);
vai->ebo = 0;
}
DecodeVerts();
goto rotateVBO;
}
} else { } else {
vai->status = VertexArrayInfo::VAI_UNRELIABLE; vai->drawsUntilNextFullHash--;
if (vai->vbo) { // TODO: "mini-hashing" the first 32 bytes of the vertex/index data or something.
glDeleteBuffers(1, &vai->vbo);
vai->vbo = 0;
}
if (vai->ebo) {
glDeleteBuffers(1, &vai->ebo);
vai->ebo = 0;
}
DecodeVerts();
goto rotateVBO;
} }
if (vai->vbo == 0) { if (vai->vbo == 0) {
DecodeVerts(); DecodeVerts();
vai->numVerts = indexGen.VertexCount(); vai->numVerts = indexGen.VertexCount();
@ -970,6 +978,7 @@ void TransformDrawEngine::Flush() {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
} }
} else { } else {
gpuStats.numCachedDrawCalls++;
glBindBuffer(GL_ARRAY_BUFFER, vai->vbo); glBindBuffer(GL_ARRAY_BUFFER, vai->vbo);
if (vai->ebo) if (vai->ebo)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vai->ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vai->ebo);

View File

@ -55,6 +55,7 @@ public:
numDraws = 0; numDraws = 0;
lastFrame = gpuStats.numFrames; lastFrame = gpuStats.numFrames;
numVerts = 0; numVerts = 0;
drawsUntilNextFullHash = 0;
} }
~VertexArrayInfo(); ~VertexArrayInfo();
enum Status { enum Status {
@ -71,6 +72,7 @@ public:
u32 vbo; u32 vbo;
u32 ebo; u32 ebo;
// TODO: see if we can avoid having this full thing here.
DecVtxFormat decFmt; DecVtxFormat decFmt;
// Precalculated parameter for drawdrawElements // Precalculated parameter for drawdrawElements
@ -81,6 +83,7 @@ public:
u8 numDCs; u8 numDCs;
int numDraws; int numDraws;
int lastFrame; // So that we can forget. int lastFrame; // So that we can forget.
u16 drawsUntilNextFullHash;
}; };