i965: Modify dirty bit handling to support 2 pipelines.
authorPaul Berry <stereotype441@gmail.com>
Sat, 11 Jan 2014 00:05:11 +0000 (16:05 -0800)
committerJordan Justen <jordan.l.justen@intel.com>
Tue, 2 Sep 2014 02:38:27 +0000 (19:38 -0700)
The hardware state for compute shaders is almost entirely orthogonal
to the hardware state for 3D rendering.  To avoid sending unnecessary
state to the hardware, we'll need to have a separate set of state
atoms for the compute pipeline and the 3D pipeline.  That means we
need to maintain two separate sets of dirty bits to determine which
state atoms need to be run.

But the dirty bits are not completely independent; for example, if
BRW_NEW_SURFACES is flagged while doing 3D rendering, then not only do
we need to re-run 3D state atoms that depend on BRW_NEW_SURFACES, but
we also need to re-run compute state atoms that depend on
BRW_NEW_SURFACES.  But we'll also need to re-run those state atoms the
next time the compute pipeline is run.

To accomplish this, we record two sets of dirty bits, one for each
pipeline.  When bits are dirtied (via SET_DIRTY_BIT() or
SET_DIRTY_ALL()) we set them to the dirty state in both pipelines.
When brw_state_upload() is run, we clear the dirty bits just for the
pipeline that was run.

Note that since the number of pipelines is known at compile time to be
2, the compiler should unroll the loops in SET_DIRTY_BIT() and
SET_DIRTY_ALL().

Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
src/mesa/drivers/dri/i965/brw_context.h
src/mesa/drivers/dri/i965/brw_draw.c
src/mesa/drivers/dri/i965/brw_state.h
src/mesa/drivers/dri/i965/brw_state_upload.c

index a44b77f4717742dfff8fc584f26bf57192362795..24bf023230bc7f359fd36047c1b819850e0e2e44 100644 (file)
@@ -242,10 +242,32 @@ struct brw_state_flags {
 };
 
 
+/**
+ * Enum representing the different pipelines.
+ */
+typedef enum {
+   /**
+    * 3D rendering pipeline (vertex through fragment shader).
+    */
+   BRW_PIPELINE_3D,
+
+   /**
+    * Compute shader pipeline.
+    */
+   BRW_PIPELINE_COMPUTE,
+
+   BRW_NUM_PIPELINES
+} brw_pipeline;
+
+
 /**
  * Set one of the bits in a field of brw_state_flags.
  */
-#define SET_DIRTY_BIT(FIELD, FLAG) brw->state.dirty.FIELD |= (FLAG)
+#define SET_DIRTY_BIT(FIELD, FLAG) \
+   do { \
+      for (int pipeline = 0; pipeline < BRW_NUM_PIPELINES; pipeline++) \
+         brw->state.pipeline_dirty[pipeline].FIELD |= (FLAG); \
+   } while (false)
 
 
 /**
@@ -254,15 +276,18 @@ struct brw_state_flags {
 #define SET_DIRTY_ALL(FIELD) \
    do { \
       /* ~0 == 0xffffffff, so make sure field is <= 32 bits */ \
-      STATIC_ASSERT(sizeof(brw->state.dirty.FIELD) == 4); \
-      brw->state.dirty.FIELD = ~0; \
+      STATIC_ASSERT(sizeof(brw->state.pipeline_dirty[0].FIELD) == 4); \
+      for (int pipeline = 0; pipeline < BRW_NUM_PIPELINES; pipeline++) \
+         brw->state.pipeline_dirty[pipeline].FIELD = ~0; \
    } while (false)
 
 
 /**
  * Check one of the bits in a field of brw_state_flags.
  */
-#define CHECK_DIRTY_BIT(FIELD, FLAG) ((brw->state.dirty.FIELD & (FLAG)) != 0)
+#define CHECK_DIRTY_BIT(FIELD, FLAG) \
+   ((brw->state.pipeline_dirty[brw->state.current_pipeline].FIELD & (FLAG)) \
+    != 0)
 
 
 /** Subclass of Mesa vertex program */
@@ -1071,7 +1096,8 @@ struct brw_context
 
    GLuint NewGLState;
    struct {
-      struct brw_state_flags dirty;
+      struct brw_state_flags pipeline_dirty[BRW_NUM_PIPELINES];
+      brw_pipeline current_pipeline;
    } state;
 
    struct brw_cache cache;
index 2b773c1ab30acb50f7b069fff944070b0bf18fa2..3bdbb43d932dab324a4a1420dcee94967377575e 100644 (file)
@@ -447,9 +447,9 @@ retry:
        * *_set_prim or intel_batchbuffer_flush(), which only impacts
        * brw->state.dirty.brw.
        */
-      if (brw->state.dirty.brw) {
+      if (brw->state.pipeline_dirty[BRW_PIPELINE_3D].brw) {
         brw->no_batch_wrap = true;
-        brw_upload_state(brw);
+        brw_upload_state(brw, BRW_PIPELINE_3D);
       }
 
       brw_emit_prim(brw, &prims[i], brw->primitive);
@@ -480,8 +480,8 @@ retry:
       /* Now that we know we haven't run out of aperture space, we can safely
        * reset the dirty bits.
        */
-      if (brw->state.dirty.brw)
-         brw_clear_dirty_bits(brw);
+      if (brw->state.pipeline_dirty[BRW_PIPELINE_3D].brw)
+         brw_clear_dirty_bits(brw, BRW_PIPELINE_3D);
    }
 
    if (brw->always_flush_batch)
index bbaa85ce35d64ac8157e9bdfa851ad0e63dc98b0..69657c10ca6988c5e70900461ba25ca0018bbf20 100644 (file)
@@ -160,8 +160,8 @@ brw_depthbuffer_format(struct brw_context *brw);
 /***********************************************************************
  * brw_state.c
  */
-void brw_upload_state(struct brw_context *brw);
-void brw_clear_dirty_bits(struct brw_context *brw);
+void brw_upload_state(struct brw_context *brw, brw_pipeline pipeline);
+void brw_clear_dirty_bits(struct brw_context *brw, brw_pipeline pipeline);
 void brw_init_state(struct brw_context *brw);
 void brw_destroy_state(struct brw_context *brw);
 
index 7324274a4068397560fb6774f0b71e7a1c8c96e5..8e45f2929628d5f47a2a4555af46751d92b4e297 100644 (file)
@@ -389,7 +389,8 @@ void brw_init_state( struct brw_context *brw )
    /* Make sure that brw->state.dirty.brw has enough bits to hold all possible
     * dirty flags.
     */
-   STATIC_ASSERT(BRW_NUM_STATE_BITS <= 8 * sizeof(brw->state.dirty.brw));
+   STATIC_ASSERT(BRW_NUM_STATE_BITS <=
+                 8 * sizeof(brw->state.pipeline_dirty[0].brw));
 
    ctx->DriverFlags.NewTransformFeedback = BRW_NEW_TRANSFORM_FEEDBACK;
    ctx->DriverFlags.NewTransformFeedbackProg = BRW_NEW_TRANSFORM_FEEDBACK;
@@ -565,13 +566,16 @@ brw_print_dirty_count(struct dirty_bit_map *bit_map)
 /***********************************************************************
  * Emit all state:
  */
-void brw_upload_state(struct brw_context *brw)
+void brw_upload_state(struct brw_context *brw, brw_pipeline pipeline)
 {
    struct gl_context *ctx = &brw->ctx;
-   struct brw_state_flags *state = &brw->state.dirty;
+   struct brw_state_flags *state = &brw->state.pipeline_dirty[pipeline];
    int i;
    static int dirty_count = 0;
 
+   assert(0 <= pipeline && pipeline < BRW_NUM_PIPELINES);
+   brw->state.current_pipeline = pipeline;
+
    SET_DIRTY_BIT(mesa, brw->NewGLState);
    brw->NewGLState = 0;
 
@@ -677,8 +681,8 @@ void brw_upload_state(struct brw_context *brw)
  * brw_upload_state() call.
  */
 void
-brw_clear_dirty_bits(struct brw_context *brw)
+brw_clear_dirty_bits(struct brw_context *brw, brw_pipeline pipeline)
 {
-   struct brw_state_flags *state = &brw->state.dirty;
+   struct brw_state_flags *state = &brw->state.pipeline_dirty[pipeline];
    memset(state, 0, sizeof(*state));
 }