[Mesa-dev] [PATCH 2/2] i965 gen6: Implement rasterizer discard.

Paul Berry stereotype441 at gmail.com
Wed Dec 14 11:59:06 PST 2011


This patch enables rasterizer discard functionality (a part of
transform feedback) in Gen6, by generating an alternate GS program
when rasterizer discard is active.  Instead of forwarding vertices
down the pipeline, the alternate GS program uses a URB Write message
to deallocate the URB entry that was allocated by FF sync and
terminate the thread.

Note: parts of the Sandy Bridge PRM seem to imply that we could do
this more efficiently, by clearing the GEN6_GS_RENDERING_ENABLE bit,
and not allocating a URB entry at all.  However, it's not clear how we
are supposed to terminate the thread if we do that.  Volume 2 part 1,
section 4.5.4, says "GS threads must terminate by sending a URB_WRITE
message with the EOT and Complete bits set.", and my experiments so
far confirm that.
---

This patch needs to be applied on top of the series "[PATCH 0/8] i965
gen6: Initial implementation of transform feedback.", which is still
under review on the mailing list.

 src/mesa/drivers/dri/i965/brw_gs.c      |    6 ++++++
 src/mesa/drivers/dri/i965/brw_gs.h      |    1 +
 src/mesa/drivers/dri/i965/brw_gs_emit.c |   30 ++++++++++++++++++++++++++++++
 3 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_gs.c b/src/mesa/drivers/dri/i965/brw_gs.c
index c323a73..2b51a4f 100644
--- a/src/mesa/drivers/dri/i965/brw_gs.c
+++ b/src/mesa/drivers/dri/i965/brw_gs.c
@@ -208,6 +208,12 @@ static void populate_key( struct brw_context *brw,
                linked_xfb_info->Outputs[i].OutputRegister;
          }
       }
+      /* On Gen6, GS is also used for rasterizer discard. */
+      /* _NEW_TRANSFORM_FEEDBACK */
+      if (ctx->TransformFeedback.RasterDiscard) {
+         key->need_gs_prog = true;
+         key->rasterizer_discard = true;
+      }
    } else {
       /* Pre-gen6, GS is used to transform QUADLIST, QUADSTRIP, and LINELOOP
        * into simpler primitives.
diff --git a/src/mesa/drivers/dri/i965/brw_gs.h b/src/mesa/drivers/dri/i965/brw_gs.h
index 33d8d7a..7bf2248 100644
--- a/src/mesa/drivers/dri/i965/brw_gs.h
+++ b/src/mesa/drivers/dri/i965/brw_gs.h
@@ -50,6 +50,7 @@ struct brw_gs_prog_key {
    GLuint pv_first:1;
    GLuint need_gs_prog:1;
    GLuint userclip_active:1;
+   GLuint rasterizer_discard:1;
 
    /**
     * Number of varyings that are output to transform feedback.
diff --git a/src/mesa/drivers/dri/i965/brw_gs_emit.c b/src/mesa/drivers/dri/i965/brw_gs_emit.c
index 72d4eca..586563a 100644
--- a/src/mesa/drivers/dri/i965/brw_gs_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_gs_emit.c
@@ -208,6 +208,28 @@ static void brw_gs_emit_vue(struct brw_gs_compile *c,
 }
 
 /**
+ * De-allocate the URB entry that was previously allocated to this thread
+ * (without writing any vertex data to it), and terminate the thread.  This is
+ * used to implement RASTERIZER_DISCARD functionality.
+ */
+static void brw_gs_terminate(struct brw_gs_compile *c)
+{
+   struct brw_compile *p = &c->func;
+   brw_urb_WRITE(p,
+                 retype(brw_null_reg(), BRW_REGISTER_TYPE_UD), /* dest */
+                 0, /* msg_reg_nr */
+                 c->reg.header, /* src0 */
+                 false, /* allocate */
+                 false, /* used */
+                 1, /* msg_length */
+                 0, /* response_length */
+                 true, /* eot */
+                 true, /* writes_complete */
+                 0, /* offset */
+                 BRW_URB_SWIZZLE_NONE);
+}
+
+/**
  * Send an FF_SYNC message to ensure that all previously spawned GS threads
  * have finished sending primitives down the pipeline, and to allocate a URB
  * entry for the first output vertex.  Only needed when intel->needs_ff_sync
@@ -414,6 +436,14 @@ gen6_sol_program(struct brw_gs_compile *c, struct brw_gs_prog_key *key,
 
    brw_gs_ff_sync(c, 1);
 
+   /* If RASTERIZER_DISCARD is enabled, we have nothing further to do, so
+    * release the URB that was just allocated, and terminate the thread.
+    */
+   if (key->rasterizer_discard) {
+      brw_gs_terminate(c);
+      return;
+   }
+
    brw_gs_overwrite_header_dw2_from_r0(c, num_verts);
    switch (num_verts) {
    case 1:
-- 
1.7.6.4



More information about the mesa-dev mailing list