i965 gen6: Implement transform feedback queries.
authorPaul Berry <stereotype441@gmail.com>
Thu, 15 Dec 2011 22:57:57 +0000 (14:57 -0800)
committerPaul Berry <stereotype441@gmail.com>
Tue, 20 Dec 2011 23:22:28 +0000 (15:22 -0800)
This patch adds software-based PRIMITIVES_GENERATED and
TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN queries that work by keeping
track of the number of primitives that are sent down the pipeline, and
adjusting as necessary to account for the way each primitive type is
tessellated.

In the long run we'll want to replace this with a hardware-based
implementation, because the software approach won't work with geometry
shaders or primitive restart.  However, at the moment, we don't have
the necessary kernel support to implement a hardware-based query (we
would need the kernel to save GPU registers when context switching, so
that drawing performed by another process doesn't get counted).

Fixes Piglit tests EXT_transform_feedback/query-primitives_generated-*
and EXT_transform_feedback/query-primitives-written-*.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/brw_context.h
src/mesa/drivers/dri/i965/brw_draw.c
src/mesa/drivers/dri/i965/brw_queryobj.c

index 8840a83d49760a332e10f7fc47f29a71af5600b9..15a781b93aebe48ebf638f9548ec953d3bd2febd 100644 (file)
@@ -988,6 +988,8 @@ struct brw_context
    struct brw_sol_state {
       uint32_t svbi_0_starting_index;
       uint32_t svbi_0_max_index;
+      uint32_t primitives_generated;
+      uint32_t primitives_written;
    } sol;
 
    uint32_t render_target_format[MESA_FORMAT_COUNT];
index 774a5ca46eeacd0120d57f95d35949fef4347b7e..082bb9aa24a4251d5b9eff200cfc8b8dc6009824 100644 (file)
@@ -388,6 +388,7 @@ brw_update_primitive_count(struct brw_context *brw,
                            const struct _mesa_prim *prim)
 {
    uint32_t count = count_tessellated_primitives(prim);
+   brw->sol.primitives_generated += count;
    if (brw->intel.ctx.TransformFeedback.CurrentObject->Active) {
       /* Update brw->sol.svbi_0_max_index to reflect the amount by which the
        * hardware is going to increment SVBI 0 when this drawing operation
@@ -404,6 +405,9 @@ brw_update_primitive_count(struct brw_context *brw,
       uint32_t primitives_written = MIN2 (space_avail, count);
       brw->sol.svbi_0_starting_index +=
          svbi_postincrement_value * primitives_written;
+
+      /* And update the TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query. */
+      brw->sol.primitives_written += primitives_written;
    }
 }
 
index 3ad522da13800ea64b539a9d13b8a004a17428ca..72b83f457086792c520c97e2121cb31710d3133e 100644 (file)
@@ -75,6 +75,14 @@ brw_queryobj_get_results(struct gl_context *ctx,
       }
       break;
 
+   case GL_PRIMITIVES_GENERATED:
+   case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+      /* We don't actually query the hardware for this value, so query->bo
+       * should always be NULL and execution should never reach here.
+       */
+      assert(!"Unreachable");
+      break;
+
    default:
       assert(!"Unrecognized query target in brw_queryobj_get_results()");
       break;
@@ -158,6 +166,20 @@ brw_begin_query(struct gl_context *ctx, struct gl_query_object *q)
       intel->stats_wm++;
       break;
 
+   case GL_PRIMITIVES_GENERATED:
+      /* We don't actually query the hardware for this value; we keep track of
+       * it a software counter.  So just reset the counter.
+       */
+      brw->sol.primitives_generated = 0;
+      break;
+
+   case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+      /* We don't actually query the hardware for this value; we keep track of
+       * it a software counter.  So just reset the counter.
+       */
+      brw->sol.primitives_written = 0;
+      break;
+
    default:
       assert(!"Unrecognized query target in brw_begin_query()");
       break;
@@ -221,6 +243,32 @@ brw_end_query(struct gl_context *ctx, struct gl_query_object *q)
       intel->stats_wm--;
       break;
 
+   case GL_PRIMITIVES_GENERATED:
+      /* We don't actually query the hardware for this value; we keep track of
+       * it in a software counter.  So just read the counter and store it in
+       * the query object.
+       */
+      query->Base.Result = brw->sol.primitives_generated;
+
+      /* And set brw->query.obj to NULL so that this query won't try to wait
+       * for any rendering to complete.
+       */
+      query->bo = NULL;
+      break;
+
+   case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+      /* We don't actually query the hardware for this value; we keep track of
+       * it in a software counter.  So just read the counter and store it in
+       * the query object.
+       */
+      query->Base.Result = brw->sol.primitives_written;
+
+      /* And set brw->query.obj to NULL so that this query won't try to wait
+       * for any rendering to complete.
+       */
+      query->bo = NULL;
+      break;
+
    default:
       assert(!"Unrecognized query target in brw_end_query()");
       break;