[Mesa-dev] [PATCH 5/6] i965 gen6: Implement transform feedback queries.

Paul Berry stereotype441 at gmail.com
Mon Dec 19 16:18:26 PST 2011


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-*.
---
 src/mesa/drivers/dri/i965/brw_context.h  |    2 +
 src/mesa/drivers/dri/i965/brw_draw.c     |    4 ++
 src/mesa/drivers/dri/i965/brw_queryobj.c |   48 ++++++++++++++++++++++++++++++
 3 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index 8840a83..15a781b 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -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];
diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c
index 774a5ca..082bb9a 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.c
+++ b/src/mesa/drivers/dri/i965/brw_draw.c
@@ -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;
    }
 }
 
diff --git a/src/mesa/drivers/dri/i965/brw_queryobj.c b/src/mesa/drivers/dri/i965/brw_queryobj.c
index 3cbd3a6..fac7070 100644
--- a/src/mesa/drivers/dri/i965/brw_queryobj.c
+++ b/src/mesa/drivers/dri/i965/brw_queryobj.c
@@ -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;
-- 
1.7.6.4



More information about the mesa-dev mailing list