Merge pull request #4343 from unknownbrackets/gpu-minor

Don't crash if there are too many vertices in a row + softgpu frameskip
This commit is contained in:
Henrik Rydgård 2013-10-28 06:49:31 -07:00
commit e0bc0a3bf1
6 changed files with 56 additions and 10 deletions

View File

@ -69,9 +69,10 @@ int D3DPrimCount(D3DPRIMITIVETYPE prim, int size) {
}
enum {
DECODED_VERTEX_BUFFER_SIZE = 65536 * 48,
DECODED_INDEX_BUFFER_SIZE = 65536 * 20,
TRANSFORMED_VERTEX_BUFFER_SIZE = 65536 * sizeof(TransformedVertex)
VERTEX_BUFFER_MAX = 65536,
DECODED_VERTEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * 48,
DECODED_INDEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * 20,
TRANSFORMED_VERTEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * sizeof(TransformedVertex)
};
@ -90,6 +91,7 @@ TransformDrawEngineDX9::TransformDrawEngineDX9()
textureCache_(0),
framebufferManager_(0),
numDrawCalls(0),
vertexCountInDrawCalls(0),
uvScale(0) {
decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL;
// Allocate nicely aligned memory. Maybe graphics drivers will
@ -914,7 +916,7 @@ void TransformDrawEngineDX9::SubmitPrim(void *verts, void *inds, GEPrimitiveType
if (vertexCount == 0)
return; // we ignore zero-sized draw calls.
if (!indexGen.PrimCompatible(prevPrim_, prim) || numDrawCalls >= MAX_DEFERRED_DRAW_CALLS)
if (!indexGen.PrimCompatible(prevPrim_, prim) || numDrawCalls >= MAX_DEFERRED_DRAW_CALLS || vertexCountInDrawCalls + vertexCount > VERTEX_BUFFER_MAX)
Flush();
// TODO: Is this the right thing to do?
@ -951,6 +953,7 @@ void TransformDrawEngineDX9::SubmitPrim(void *verts, void *inds, GEPrimitiveType
uvScale[numDrawCalls] = gstate_c.uv;
}
numDrawCalls++;
vertexCountInDrawCalls += vertexCount;
}
void TransformDrawEngineDX9::DecodeVerts() {
@ -1330,6 +1333,7 @@ rotateVBO:
indexGen.Reset();
collectedVerts = 0;
numDrawCalls = 0;
vertexCountInDrawCalls = 0;
prevPrim_ = GE_PRIM_INVALID;
#ifndef _XBOX

View File

@ -186,6 +186,7 @@ private:
enum { MAX_DEFERRED_DRAW_CALLS = 128 };
DeferredDrawCall drawCalls[MAX_DEFERRED_DRAW_CALLS];
int numDrawCalls;
int vertexCountInDrawCalls;
int decimationCounter_;

View File

@ -99,9 +99,10 @@ const GLuint glprim[8] = {
};
enum {
DECODED_VERTEX_BUFFER_SIZE = 65536 * 48,
DECODED_INDEX_BUFFER_SIZE = 65536 * 20,
TRANSFORMED_VERTEX_BUFFER_SIZE = 65536 * sizeof(TransformedVertex)
VERTEX_BUFFER_MAX = 65536,
DECODED_VERTEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * 48,
DECODED_INDEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * 20,
TRANSFORMED_VERTEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * sizeof(TransformedVertex)
};
#define QUAD_INDICES_MAX 32768
@ -123,6 +124,7 @@ TransformDrawEngine::TransformDrawEngine()
textureCache_(0),
framebufferManager_(0),
numDrawCalls(0),
vertexCountInDrawCalls(0),
uvScale(0) {
decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL;
// Allocate nicely aligned memory. Maybe graphics drivers will
@ -914,7 +916,7 @@ void TransformDrawEngine::SubmitPrim(void *verts, void *inds, GEPrimitiveType pr
if (vertexCount == 0)
return; // we ignore zero-sized draw calls.
if (!indexGen.PrimCompatible(prevPrim_, prim) || numDrawCalls >= MAX_DEFERRED_DRAW_CALLS)
if (!indexGen.PrimCompatible(prevPrim_, prim) || numDrawCalls >= MAX_DEFERRED_DRAW_CALLS || vertexCountInDrawCalls + vertexCount > VERTEX_BUFFER_MAX)
Flush();
// TODO: Is this the right thing to do?
@ -951,6 +953,7 @@ void TransformDrawEngine::SubmitPrim(void *verts, void *inds, GEPrimitiveType pr
uvScale[numDrawCalls] = gstate_c.uv;
}
numDrawCalls++;
vertexCountInDrawCalls += vertexCount;
}
void TransformDrawEngine::DecodeVerts() {
@ -1326,6 +1329,7 @@ rotateVBO:
indexGen.Reset();
collectedVerts = 0;
numDrawCalls = 0;
vertexCountInDrawCalls = 0;
prevPrim_ = GE_PRIM_INVALID;
#ifndef USING_GLES2

View File

@ -191,6 +191,7 @@ private:
enum { MAX_DEFERRED_DRAW_CALLS = 128 };
DeferredDrawCall drawCalls[MAX_DEFERRED_DRAW_CALLS];
int numDrawCalls;
int vertexCountInDrawCalls;
int decimationCounter_;

View File

@ -268,6 +268,32 @@ void SoftGPU::FastRunLoop(DisplayList &list) {
}
}
int EstimatePerVertexCost() {
// TODO: This is transform cost, also account for rasterization cost somehow... although it probably
// runs in parallel with transform.
// Also, this is all pure guesswork. If we can find a way to do measurements, that would be great.
// GTA wants a low value to run smooth, GoW wants a high value (otherwise it thinks things
// went too fast and starts doing all the work over again).
int cost = 20;
if (gstate.isLightingEnabled()) {
cost += 10;
}
for (int i = 0; i < 4; i++) {
if (gstate.isLightChanEnabled(i))
cost += 10;
}
if (gstate.getUVGenMode() != GE_TEXMAP_TEXTURE_COORDS) {
cost += 20;
}
// TODO: morphcount
return cost;
}
void SoftGPU::ExecuteOp(u32 op, u32 diff)
{
u32 cmd = op >> 24;
@ -303,6 +329,7 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff)
if (type != GE_PRIM_TRIANGLES && type != GE_PRIM_TRIANGLE_STRIP && type != GE_PRIM_TRIANGLE_FAN && type != GE_PRIM_RECTANGLES) {
ERROR_LOG_REPORT(G3D, "Software: DL DrawPrim type: %s count: %i vaddr= %08x, iaddr= %08x", type<7 ? types[type] : "INVALID", count, gstate_c.vertexAddr, gstate_c.indexAddr);
cyclesExecuted += EstimatePerVertexCost() * count;
break;
}
@ -321,7 +348,10 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff)
indices = Memory::GetPointer(gstate_c.indexAddr);
}
TransformUnit::SubmitPrimitive(verts, indices, type, count, gstate.vertType);
cyclesExecuted += EstimatePerVertexCost() * count;
if (!(gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME)) {
TransformUnit::SubmitPrimitive(verts, indices, type, count, gstate.vertType);
}
}
break;
@ -361,7 +391,9 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff)
break;
}
TransformUnit::SubmitSpline(control_points, indices, sp_ucount, sp_vcount, sp_utype, sp_vtype, gstate.getPatchPrimitiveType(), gstate.vertType);
if (!(gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME)) {
TransformUnit::SubmitSpline(control_points, indices, sp_ucount, sp_vcount, sp_utype, sp_vtype, gstate.getPatchPrimitiveType(), gstate.vertType);
}
DEBUG_LOG(G3D,"DL DRAW SPLINE: %i x %i, %i x %i", sp_ucount, sp_vcount, sp_utype, sp_vtype);
}
break;

View File

@ -73,6 +73,10 @@ public:
fullInfo = "Software";
}
virtual bool FramebufferReallyDirty() {
return !(gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME);
}
virtual bool GetCurrentFramebuffer(GPUDebugBuffer &buffer);
virtual bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer);
virtual bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer);