i965/state: Create separate dirty state bits for each pipeline
authorJordan Justen <jordan.l.justen@intel.com>
Sun, 8 Mar 2015 07:21:46 +0000 (23:21 -0800)
committerJordan Justen <jordan.l.justen@intel.com>
Tue, 31 Mar 2015 23:40:24 +0000 (16:40 -0700)
When clearing the state for a pipeline, we will save changed state for
the other pipelines.

v3:
 * Adjust brw_upload_pipeline_state
   * Don't pull pipeline state bits into common state bits
   * Don't clear pipeline state bits
 * Adjust 'clear' phase
   * brw_clear_dirty_bits is now brw_render_state_finished
   * Move cross-pipeline state flagging to brw_pipeline_state_finished
   * Move pipeline clears to brw_pipeline_state_finished

Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Kristian Høgsberg <krh@bitplanet.net>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/brw_context.h
src/mesa/drivers/dri/i965/brw_state_upload.c

index e1481d5ce99f83439327d135e55510b137b7ae52..52b27a95eca8d79c7b6f3d81092c7a289f5ed509 100644 (file)
@@ -1117,6 +1117,7 @@ struct brw_context
    GLuint NewGLState;
    struct {
       struct brw_state_flags dirty;
+      struct brw_state_flags pipelines[BRW_NUM_PIPELINES];
    } state;
 
    struct brw_cache cache;
index b15d8c5e4824d5cb90b0e0b0c16fe03fcd62877e..8bd88f138d92d5de689ff6258cf74d07a4f0c974 100644 (file)
@@ -596,26 +596,45 @@ brw_upload_programs(struct brw_context *brw)
    brw_upload_wm_prog(brw);
 }
 
-/***********************************************************************
- * Emit all state:
- */
-void brw_upload_render_state(struct brw_context *brw)
+static inline void
+merge_ctx_state(struct brw_context *brw,
+                struct brw_state_flags *state)
+{
+   state->mesa |= brw->state.dirty.mesa;
+   state->brw |= brw->state.dirty.brw;
+}
+
+static inline void
+check_and_emit_atom(struct brw_context *brw,
+                    struct brw_state_flags *state,
+                    const struct brw_tracked_state *atom)
+{
+   if (check_state(state, &atom->dirty)) {
+      atom->emit(brw);
+      merge_ctx_state(brw, state);
+   }
+}
+
+static inline void
+brw_upload_pipeline_state(struct brw_context *brw,
+                          enum brw_pipeline pipeline)
 {
    struct gl_context *ctx = &brw->ctx;
-   struct brw_state_flags *state = &brw->state.dirty;
+   struct brw_state_flags *brw_state = &brw->state.dirty;
    int i;
    static int dirty_count = 0;
+   struct brw_state_flags state = brw->state.pipelines[pipeline];
 
-   state->mesa |= brw->NewGLState;
+   brw_state->mesa |= brw->NewGLState;
    brw->NewGLState = 0;
 
-   state->brw |= ctx->NewDriverState;
+   brw_state->brw |= ctx->NewDriverState;
    ctx->NewDriverState = 0;
 
    if (0) {
       /* Always re-emit all state. */
-      state->mesa |= ~0;
-      state->brw |= ~0ull;
+      brw_state->mesa |= ~0;
+      brw_state->brw |= ~0ull;
    }
 
    if (brw->fragment_program != ctx->FragmentProgram._Current) {
@@ -643,7 +662,9 @@ void brw_upload_render_state(struct brw_context *brw)
       brw->state.dirty.brw |= BRW_NEW_NUM_SAMPLES;
    }
 
-   if ((state->mesa | state->brw) == 0)
+   /* Exit early if no state is flagged as dirty */
+   merge_ctx_state(brw, &state);
+   if ((state.mesa | state.brw) == 0)
       return;
 
    /* Emit Sandybridge workaround flushes on every primitive, for safety. */
@@ -651,6 +672,11 @@ void brw_upload_render_state(struct brw_context *brw)
       intel_emit_post_sync_nonzero_flush(brw);
 
    brw_upload_programs(brw);
+   merge_ctx_state(brw, &state);
+
+   const struct brw_tracked_state *atoms =
+      brw_get_pipeline_atoms(brw, pipeline);
+   const int num_atoms = brw->num_atoms[pipeline];
 
    if (unlikely(INTEL_DEBUG)) {
       /* Debug version which enforces various sanity checks on the
@@ -659,15 +685,13 @@ void brw_upload_render_state(struct brw_context *brw)
        */
       struct brw_state_flags examined, prev;
       memset(&examined, 0, sizeof(examined));
-      prev = *state;
+      prev = state;
 
-      for (i = 0; i < brw->num_atoms[BRW_RENDER_PIPELINE]; i++) {
-        const struct brw_tracked_state *atom = &brw->render_atoms[i];
+      for (i = 0; i < num_atoms; i++) {
+        const struct brw_tracked_state *atom = &atoms[i];
         struct brw_state_flags generated;
 
-        if (check_state(state, &atom->dirty)) {
-           atom->emit(brw);
-        }
+         check_and_emit_atom(brw, &state, atom);
 
         accumulate_state(&examined, &atom->dirty);
 
@@ -675,26 +699,24 @@ void brw_upload_render_state(struct brw_context *brw)
          * if (examined & generated)
          *     fail;
          */
-        xor_states(&generated, &prev, state);
+        xor_states(&generated, &prev, &state);
         assert(!check_state(&examined, &generated));
-        prev = *state;
+        prev = state;
       }
    }
    else {
-      for (i = 0; i < brw->num_atoms[BRW_RENDER_PIPELINE]; i++) {
-        const struct brw_tracked_state *atom = &brw->render_atoms[i];
+      for (i = 0; i < num_atoms; i++) {
+        const struct brw_tracked_state *atom = &atoms[i];
 
-        if (check_state(state, &atom->dirty)) {
-           atom->emit(brw);
-        }
+         check_and_emit_atom(brw, &state, atom);
       }
    }
 
    if (unlikely(INTEL_DEBUG & DEBUG_STATE)) {
       STATIC_ASSERT(ARRAY_SIZE(brw_bits) == BRW_NUM_STATE_BITS + 1);
 
-      brw_update_dirty_count(mesa_bits, state->mesa);
-      brw_update_dirty_count(brw_bits, state->brw);
+      brw_update_dirty_count(mesa_bits, state.mesa);
+      brw_update_dirty_count(brw_bits, state.brw);
       if (dirty_count++ % 1000 == 0) {
         brw_print_dirty_count(mesa_bits);
         brw_print_dirty_count(brw_bits);
@@ -703,6 +725,32 @@ void brw_upload_render_state(struct brw_context *brw)
    }
 }
 
+/***********************************************************************
+ * Emit all state:
+ */
+void brw_upload_render_state(struct brw_context *brw)
+{
+   brw_upload_pipeline_state(brw, BRW_RENDER_PIPELINE);
+}
+
+static inline void
+brw_pipeline_state_finished(struct brw_context *brw,
+                            enum brw_pipeline pipeline)
+{
+   struct brw_state_flags *state = &brw->state.dirty;
+
+   /* Save all dirty state into the other pipelines */
+   for (int i = 0; i < BRW_NUM_PIPELINES; i++) {
+      if (i != pipeline) {
+         brw->state.pipelines[i].mesa |= state->mesa;
+         brw->state.pipelines[i].brw |= state->brw;
+      } else {
+         memset(&brw->state.pipelines[i], 0, sizeof(struct brw_state_flags));
+      }
+   }
+
+   memset(state, 0, sizeof(*state));
+}
 
 /**
  * Clear dirty bits to account for the fact that the state emitted by
@@ -715,6 +763,5 @@ void brw_upload_render_state(struct brw_context *brw)
 void
 brw_render_state_finished(struct brw_context *brw)
 {
-   struct brw_state_flags *state = &brw->state.dirty;
-   memset(state, 0, sizeof(*state));
+   brw_pipeline_state_finished(brw, BRW_RENDER_PIPELINE);
 }