i965: Reduce fast-pathiness of brw_try_draw_prims, bringing in important checks.
authorEric Anholt <eric@anholt.net>
Thu, 27 Nov 2008 03:22:37 +0000 (19:22 -0800)
committerEric Anholt <eric@anholt.net>
Sat, 29 Nov 2008 01:09:45 +0000 (17:09 -0800)
Later primitives, even if they caused a full state validate, wouldn't check
that there was enough space in the batchbuffer, occasionally triggering the
sanity check.  We also skipped the aperture space check, even if it would
mean bringing in new programs and associated state.

src/mesa/drivers/dri/i965/brw_draw.c

index f893dd6742309cab977ae8d6fbfe1ea807daa936..c3a26fc82eb71f132b203b41187015e82509a8ba 100644 (file)
@@ -49,7 +49,7 @@
 
 #define FILE_DEBUG_FLAG DEBUG_BATCH
 
-static GLuint hw_prim[GL_POLYGON+1] = {
+static GLuint prim_to_hw_prim[GL_POLYGON+1] = {
    _3DPRIM_POINTLIST,
    _3DPRIM_LINELIST,
    _3DPRIM_LINELOOP,
@@ -103,12 +103,9 @@ static GLuint brw_set_prim(struct brw_context *brw, GLenum prim)
         brw->intel.reduced_primitive = reduced_prim[prim];
         brw->state.dirty.brw |= BRW_NEW_REDUCED_PRIMITIVE;
       }
-
-      brw_validate_state(brw);
-      brw_upload_state(brw);
    }
 
-   return hw_prim[prim];
+   return prim_to_hw_prim[prim];
 }
 
 
@@ -123,9 +120,9 @@ static GLuint trim(GLenum prim, GLuint length)
 }
 
 
-static void brw_emit_prim( struct brw_context *brw, 
-                          const struct _mesa_prim *prim )
-
+static void brw_emit_prim(struct brw_context *brw,
+                         const struct _mesa_prim *prim,
+                         uint32_t hw_prim)
 {
    struct brw_3d_primitive prim_packet;
 
@@ -136,7 +133,7 @@ static void brw_emit_prim( struct brw_context *brw,
    prim_packet.header.opcode = CMD_3D_PRIM;
    prim_packet.header.length = sizeof(prim_packet)/4 - 2;
    prim_packet.header.pad = 0;
-   prim_packet.header.topology = brw_set_prim(brw, prim->mode);
+   prim_packet.header.topology = hw_prim;
    prim_packet.header.indexed = prim->indexed;
 
    prim_packet.verts_per_instance = trim(prim->mode, prim->count);
@@ -258,11 +255,15 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx,
    struct brw_context *brw = brw_context(ctx);
    GLboolean retval = GL_FALSE;
    GLboolean warn = GL_FALSE;
+   GLboolean first_time = GL_TRUE;
    GLuint i;
 
    if (ctx->NewState)
       _mesa_update_state( ctx );
 
+   if (check_fallbacks(brw, prim, nr_prims))
+      return GL_FALSE;
+
    brw_validate_textures( brw );
 
    /* Bind all inputs, derive varying and size information:
@@ -275,6 +276,7 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx,
    brw->vb.min_index = min_index;
    brw->vb.max_index = max_index;
    brw->state.dirty.brw |= BRW_NEW_VERTICES;
+
    /* Have to validate state quite late.  Will rebuild tnl_program,
     * which depends on varying information.  
     * 
@@ -289,59 +291,58 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx,
       return GL_TRUE;
    }
 
-   /* Flush the batch if it's approaching full, so that we don't wrap while
-    * we've got validated state that needs to be in the same batch as the
-    * primitives.  This fraction is just a guess (minimal full state plus
-    * a primitive is around 512 bytes), and would be better if we had
-    * an upper bound of how much we might emit in a single
-    * brw_try_draw_prims().
-    */
-   intel_batchbuffer_require_space(intel->batch, intel->batch->size / 4,
-                                  LOOP_CLIPRECTS);
-   {
-      /* Set the first primitive early, ahead of validate_state:
+   for (i = 0; i < nr_prims; i++) {
+      uint32_t hw_prim;
+
+      /* Flush the batch if it's approaching full, so that we don't wrap while
+       * we've got validated state that needs to be in the same batch as the
+       * primitives.  This fraction is just a guess (minimal full state plus
+       * a primitive is around 512 bytes), and would be better if we had
+       * an upper bound of how much we might emit in a single
+       * brw_try_draw_prims().
        */
-      brw_set_prim(brw, prim[0].mode);
+      intel_batchbuffer_require_space(intel->batch, intel->batch->size / 4,
+                                     LOOP_CLIPRECTS);
 
-      brw_validate_state( brw );
+      hw_prim = brw_set_prim(brw, prim[i].mode);
 
-      /* Various fallback checks:
-       */
-      if (brw->intel.Fallback) 
-        goto out;
+      if (first_time || (brw->state.dirty.brw & BRW_NEW_PRIMITIVE)) {
+        first_time = GL_FALSE;
 
-      if (check_fallbacks( brw, prim, nr_prims ))
-        goto out;
+        /* Various fallback checks:  */
+        if (brw->intel.Fallback)
+           goto out;
 
-      /* Check that we can fit our state in with our existing batchbuffer, or
-       * flush otherwise.
-       */
-      if (dri_bufmgr_check_aperture_space(brw->state.validated_bos,
-                                         brw->state.validated_bo_count)) {
-        static GLboolean warned;
-        intel_batchbuffer_flush(intel->batch);
-
-        /* Validate the state after we flushed the batch (which would have
-         * changed the set of dirty state).  If we still fail to
-         * check_aperture, warn of what's happening, but attempt to continue
-         * on since it may succeed anyway, and the user would probably rather
-         * see a failure and a warning than a fallback.
-         */
         brw_validate_state(brw);
-        if (!warned &&
-            dri_bufmgr_check_aperture_space(brw->state.validated_bos,
+
+        /* Check that we can fit our state in with our existing batchbuffer, or
+         * flush otherwise.
+         */
+        if (dri_bufmgr_check_aperture_space(brw->state.validated_bos,
                                             brw->state.validated_bo_count)) {
-           warn = GL_TRUE;
-           warned = GL_TRUE;
+           static GLboolean warned;
+           intel_batchbuffer_flush(intel->batch);
+
+           /* Validate the state after we flushed the batch (which would have
+            * changed the set of dirty state).  If we still fail to
+            * check_aperture, warn of what's happening, but attempt to continue
+            * on since it may succeed anyway, and the user would probably rather
+            * see a failure and a warning than a fallback.
+            */
+           brw_validate_state(brw);
+           if (!warned &&
+               dri_bufmgr_check_aperture_space(brw->state.validated_bos,
+                                               brw->state.validated_bo_count)) {
+              warn = GL_TRUE;
+              warned = GL_TRUE;
+           }
         }
-      }
-
-      brw_upload_state(brw);
 
-      for (i = 0; i < nr_prims; i++) {
-        brw_emit_prim(brw, &prim[i]);
+        brw_upload_state(brw);
       }
 
+      brw_emit_prim(brw, &prim[i], hw_prim);
+
       retval = GL_TRUE;
    }