diff options
Diffstat (limited to 'src/mesa/drivers/dri/r600/r700_render.c')
-rw-r--r-- | src/mesa/drivers/dri/r600/r700_render.c | 59 |
1 files changed, 51 insertions, 8 deletions
diff --git a/src/mesa/drivers/dri/r600/r700_render.c b/src/mesa/drivers/dri/r600/r700_render.c index cdf3220a7f..d64e921bda 100644 --- a/src/mesa/drivers/dri/r600/r700_render.c +++ b/src/mesa/drivers/dri/r600/r700_render.c @@ -53,6 +53,8 @@ #include "r700_fragprog.h" #include "r700_state.h" +#include "radeon_common_context.h" + void r700WaitForIdle(context_t *context); void r700WaitForIdleClean(context_t *context); GLboolean r700SendTextureState(context_t *context); @@ -298,22 +300,52 @@ static void r700RunRenderPrimitive(GLcontext * ctx, int start, int end, int prim } +/* start 3d, idle, cb/db flush */ +#define PRE_EMIT_STATE_BUFSZ 10 + 5 + 14 + +static GLuint r700PredictRenderSize(GLcontext* ctx) +{ + context_t *context = R700_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct r700_vertex_program *vpc + = (struct r700_vertex_program *)ctx->VertexProgram._Current; + struct vertex_buffer *vb = &tnl->vb; + GLboolean flushed; + GLuint dwords, i; + GLuint state_size; + /* pre calculate aos count so state prediction works */ + context->radeon.tcl.aos_count = _mesa_bitcount(vpc->mesa_program.Base.InputsRead); + + dwords = PRE_EMIT_STATE_BUFSZ; + for (i = 0; i < vb->PrimitiveCount; i++) + dwords += vb->Primitive[i].count + 10; + state_size = radeonCountStateEmitSize(&context->radeon); + flushed = rcommonEnsureCmdBufSpace(&context->radeon, + dwords + state_size, __FUNCTION__); + + if (flushed) + dwords += radeonCountStateEmitSize(&context->radeon); + else + dwords += state_size; + + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "%s: total prediction size is %d.\n", __FUNCTION__, dwords); + return dwords; +} + static GLboolean r700RunRender(GLcontext * ctx, struct tnl_pipeline_stage *stage) { context_t *context = R700_CONTEXT(ctx); radeonContextPtr radeon = &context->radeon; - unsigned int i, ind_count = 0, id = 0; + unsigned int i, id = 0; TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *vb = &tnl->vb; struct radeon_renderbuffer *rrb; - for (i = 0; i < vb->PrimitiveCount; i++) - ind_count += vb->Primitive[i].count + 10; - - /* just an estimate, need to properly calculate this */ - rcommonEnsureCmdBufSpace(&context->radeon, - radeon->hw.max_state_size + ind_count, __FUNCTION__); + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "%s: cs begin at %d\n", + __func__, context->radeon.cmdbuf.cs->cdw); /* always emit CB base to prevent * lock ups on some chips. @@ -327,6 +359,9 @@ static GLboolean r700RunRender(GLcontext * ctx, r700SetupVertexProgram(ctx); r700SetupFragmentProgram(ctx); r600UpdateTextureState(ctx); + + GLuint emit_end = r700PredictRenderSize(ctx) + + context->radeon.cmdbuf.cs->cdw; r700SetupStreams(ctx); radeonEmitState(radeon); @@ -336,7 +371,7 @@ static GLboolean r700RunRender(GLcontext * ctx, GLuint prim = _tnl_translate_prim(&vb->Primitive[i]); GLuint start = vb->Primitive[i].start; GLuint end = vb->Primitive[i].start + vb->Primitive[i].count; - r700RunRenderPrimitive(ctx, start, end, prim); + r700RunRenderPrimitive(ctx, start, end, prim); } /* Flush render op cached for last several quads. */ @@ -354,6 +389,14 @@ static GLboolean r700RunRender(GLcontext * ctx, radeonReleaseArrays(ctx, ~0); + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "%s: cs end at %d\n", + __func__, context->radeon.cmdbuf.cs->cdw); + + if ( emit_end < context->radeon.cmdbuf.cs->cdw ) + WARN_ONCE("Rendering was %d commands larger than predicted size." + " We might overflow command buffer.\n", context->radeon.cmdbuf.cs->cdw - emit_end); + return GL_FALSE; } |