radeon/r200/r300/r600: Warn if we emit more than prediction was.
authorPauli Nieminen <suokkos@gmail.com>
Mon, 24 Aug 2009 23:23:52 +0000 (02:23 +0300)
committerPauli Nieminen <suokkos@gmail.com>
Mon, 24 Aug 2009 23:23:52 +0000 (02:23 +0300)
Prediction code making too small prediction may cause space check aserttion
failure later in rendering. So warning about any failure to predict correctly
should be fixed.

src/mesa/drivers/dri/r200/r200_tcl.c
src/mesa/drivers/dri/r300/r300_draw.c
src/mesa/drivers/dri/r600/r700_render.c
src/mesa/drivers/dri/radeon/radeon_tcl.c

index 0f5e501c1a61172681c76702a4b964dad42645c2..7b3a9fc859da8543eacd197bb274a0b095ea4416 100644 (file)
@@ -51,6 +51,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r200_swtcl.h"
 #include "r200_maos.h"
 
+#include "radeon_common_context.h"
+
 
 
 #define HAVE_POINTS      1
@@ -368,12 +370,13 @@ r200ComputeFogBlendFactor( GLcontext *ctx, GLfloat fogcoord )
  * Predict total emit size for next rendering operation so there is no flush in middle of rendering
  * Prediction has to aim towards the best possible value that is worse than worst case scenario
  */
-static void r200EnsureEmitSize( GLcontext * ctx , GLubyte* vimap_rev )
+static GLuint r200EnsureEmitSize( GLcontext * ctx , GLubyte* vimap_rev )
 {
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
   TNLcontext *tnl = TNL_CONTEXT(ctx);
   struct vertex_buffer *VB = &tnl->vb;
   GLuint space_required;
+  GLuint state_size;
   GLuint nr_aos = 0;
   int i;
   /* predict number of aos to emit */
@@ -387,10 +390,11 @@ static void r200EnsureEmitSize( GLcontext * ctx , GLubyte* vimap_rev )
 
   {
     /* count the prediction for state size */
-    space_required = radeonCountStateEmitSize( &rmesa->radeon );
+    space_required = 0;
+    state_size = radeonCountStateEmitSize( &rmesa->radeon );
     /* vtx may be changed in r200EmitArrays so account for it if not dirty */
     if (!rmesa->hw.vtx.dirty)
-      space_required += rmesa->hw.vtx.check(rmesa->radeon.glCtx, &rmesa->hw.vtx);
+      state_size += rmesa->hw.vtx.check(rmesa->radeon.glCtx, &rmesa->hw.vtx);
     /* predict size for elements */
     for (i = 0; i < VB->PrimitiveCount; ++i)
     {
@@ -413,7 +417,10 @@ static void r200EnsureEmitSize( GLcontext * ctx , GLubyte* vimap_rev )
     space_required += SCISSOR_BUFSZ;
   }
   /* flush the buffer in case we need more than is left. */
-  rcommonEnsureCmdBufSpace(&rmesa->radeon, space_required, __FUNCTION__);
+  if (rcommonEnsureCmdBufSpace(&rmesa->radeon, space_required + state_size, __FUNCTION__))
+    return space_required + radeonCountStateEmitSize( &rmesa->radeon );
+  else
+    return space_required + state_size;
 }
 
 
@@ -530,7 +537,8 @@ static GLboolean r200_run_tcl_render( GLcontext *ctx,
    /* Do the actual work:
     */
    radeonReleaseArrays( ctx, ~0 /* stage->changed_inputs */ );
-   r200EnsureEmitSize( ctx, vimap_rev );
+   GLuint emit_end = r200EnsureEmitSize( ctx, vimap_rev )
+     + rmesa->radeon.cmdbuf.cs->cdw;
    r200EmitArrays( ctx, vimap_rev );
 
    for (i = 0 ; i < VB->PrimitiveCount ; i++)
@@ -547,6 +555,9 @@ static GLboolean r200_run_tcl_render( GLcontext *ctx,
       else
         r200EmitPrimitive( ctx, start, start+length, prim );
    }
+   if ( emit_end < rmesa->radeon.cmdbuf.cs->cdw )
+     WARN_ONCE("Rendering was %d commands larger than predicted size."
+        " We might overflow  command buffer.\n", rmesa->radeon.cmdbuf.cs->cdw - emit_end);
 
    return GL_FALSE;            /* finished the pipe */
 }
index 2ac898bd59de6308aa24e4666f9163414c779ba2..56680516c8315046d340b6f5ee4bf78f75c078ab 100644 (file)
@@ -42,6 +42,7 @@
 #include "r300_cmdbuf.h"
 
 #include "radeon_buffer_objects.h"
+#include "radeon_common_context.h"
 
 #include "tnl/tnl.h"
 #include "tnl/t_vp_build.h"
@@ -632,7 +633,8 @@ static GLboolean r300TryDrawPrims(GLcontext *ctx,
 
        /* ensure we have the cmd buf space in advance to cover
         * the state + DMA AOS pointers */
-       r300PredictTryDrawPrimsSize(ctx, nr_prims);
+       GLuint emit_end = r300PredictTryDrawPrimsSize(ctx, nr_prims)
+               + r300->radeon.cmdbuf.cs->cdw;
 
        r300SetupIndexBuffer(ctx, ib);
 
@@ -656,6 +658,10 @@ static GLboolean r300TryDrawPrims(GLcontext *ctx,
                fprintf(stderr, "%s: %u (%d-%d) cs ending at %d\n",
                        __FUNCTION__, nr_prims, min_index, max_index, r300->radeon.cmdbuf.cs->cdw );
 
+       if (emit_end < r300->radeon.cmdbuf.cs->cdw)
+               WARN_ONCE("Rendering was %d commands larger than predicted size."
+                               " We might overflow  command buffer.\n", r300->radeon.cmdbuf.cs->cdw - emit_end);
+
        return GL_TRUE;
 }
 
index 899c2cf05c3f78f6a0bc5b04e6b04aa6082e0d8c..9b0b5443d6aeb5a37f168023a119ddcf34abe556 100644 (file)
@@ -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);
@@ -384,7 +386,9 @@ static GLboolean r700RunRender(GLcontext * ctx,
         fprintf(stderr, "%s: cs end at %d\n",
                 __func__, context->radeon.cmdbuf.cs->cdw);
 
-    assert(context->radeon.cmdbuf.cs->cdw <= emit_end);
+    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;
 }
index 908b3c9f0615703710da0984cf3dce98c4101d07..2404f284505849ff63dc79fd11850c17a124c722 100644 (file)
@@ -50,6 +50,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "radeon_tcl.h"
 #include "radeon_swtcl.h"
 #include "radeon_maos.h"
+#include "radeon_common_context.h"
 
 
 
@@ -359,12 +360,13 @@ radeonComputeFogBlendFactor( GLcontext *ctx, GLfloat fogcoord )
  * Predict total emit size for next rendering operation so there is no flush in middle of rendering
  * Prediction has to aim towards the best possible value that is worse than worst case scenario
  */
-static void radeonEnsureEmitSize( GLcontext * ctx , GLuint inputs )
+static GLuint radeonEnsureEmitSize( GLcontext * ctx , GLuint inputs )
 {
   r100ContextPtr rmesa = R100_CONTEXT(ctx);
   TNLcontext *tnl = TNL_CONTEXT(ctx);
   struct vertex_buffer *VB = &tnl->vb;
   GLuint space_required;
+  GLuint state_size;
   GLuint nr_aos = 1; /* radeonEmitArrays does always emit one */
   int i;
   /* list of flags that are allocating aos object */
@@ -388,10 +390,11 @@ static void radeonEnsureEmitSize( GLcontext * ctx , GLuint inputs )
 
   {
     /* count the prediction for state size */
-    space_required = radeonCountStateEmitSize( &rmesa->radeon );
+    space_required = 0;
+    state_size = radeonCountStateEmitSize( &rmesa->radeon );
     /* tcl may be changed in radeonEmitArrays so account for it if not dirty */
     if (!rmesa->hw.tcl.dirty)
-      space_required += rmesa->hw.tcl.check( rmesa->radeon.glCtx, &rmesa->hw.tcl );
+      state_size += rmesa->hw.tcl.check( rmesa->radeon.glCtx, &rmesa->hw.tcl );
     /* predict size for elements */
     for (i = 0; i < VB->PrimitiveCount; ++i)
     {
@@ -414,7 +417,10 @@ static void radeonEnsureEmitSize( GLcontext * ctx , GLuint inputs )
     space_required += SCISSOR_BUFSZ;
   }
   /* flush the buffer in case we need more than is left. */
-  rcommonEnsureCmdBufSpace(&rmesa->radeon, space_required, __FUNCTION__);
+  if (rcommonEnsureCmdBufSpace(&rmesa->radeon, space_required, __FUNCTION__))
+    return space_required + radeonCountStateEmitSize( &rmesa->radeon );
+  else
+    return space_required + state_size;
 }
 
 /**********************************************************************/
@@ -467,7 +473,8 @@ static GLboolean radeon_run_tcl_render( GLcontext *ctx,
    }
 
    radeonReleaseArrays( ctx, ~0 );
-   radeonEnsureEmitSize( ctx, inputs );
+   GLuint emit_end = radeonEnsureEmitSize( ctx, inputs )
+     + rmesa->radeon.cmdbuf.cs->cdw;
    radeonEmitArrays( ctx, inputs );
 
    rmesa->tcl.Elts = VB->Elts;
@@ -487,6 +494,10 @@ static GLboolean radeon_run_tcl_render( GLcontext *ctx,
         radeonEmitPrimitive( ctx, start, start+length, prim );
    }
 
+   if (emit_end < rmesa->radeon.cmdbuf.cs->cdw)
+      WARN_ONCE("Rendering was %d commands larger than predicted size."
+         " We might overflow  command buffer.\n", rmesa->radeon.cmdbuf.cs->cdw - emit_end);
+
    return GL_FALSE;            /* finished the pipe */
 }