[Mesa-dev] [PATCH 06/11] i965: Separate uploading push constant data from the pointer packets.

Kenneth Graunke kenneth at whitecape.org
Fri Jul 7 00:22:15 UTC 2017


I hope to upload UBO via 3DSTATE_CONSTANT_XS packets, in addition to
normal uniforms.  In order to do that, I'll need to re-emit the packets
when UBOs change.  But I don't want to re-copy the regular uniform data
to the batchbuffer every time.

This patch separates out the data uploading from the packet submission.
We're running low on dirty bits, so I made the new atom happen on every
draw call, and added a flag to stage_state indicating that we want the
packet for that stage emitted.

I would have preferred to do this outside the atom system, but it has
to happen between the uploading of push constant data and the binding
table upload.
---
 src/mesa/drivers/dri/i965/brw_context.h         |  3 +
 src/mesa/drivers/dri/i965/gen6_constant_state.c |  2 +
 src/mesa/drivers/dri/i965/genX_state_upload.c   | 81 ++++++++++++++-----------
 3 files changed, 52 insertions(+), 34 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index 3f233d815b2..29dbc1726c3 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -565,6 +565,9 @@ struct brw_stage_state
    /** SAMPLER_STATE count and table offset */
    uint32_t sampler_count;
    uint32_t sampler_offset;
+
+   /** Need to re-emit 3DSTATE_CONSTANT_XS? */
+   bool push_constants_dirty;
 };
 
 enum brw_predicate_state {
diff --git a/src/mesa/drivers/dri/i965/gen6_constant_state.c b/src/mesa/drivers/dri/i965/gen6_constant_state.c
index 920f502ca37..dd4e224aada 100644
--- a/src/mesa/drivers/dri/i965/gen6_constant_state.c
+++ b/src/mesa/drivers/dri/i965/gen6_constant_state.c
@@ -119,4 +119,6 @@ gen6_upload_push_constants(struct brw_context *brw,
        */
       assert(stage_state->push_const_size <= 32);
    }
+
+   stage_state->push_constants_dirty = true;
 }
diff --git a/src/mesa/drivers/dri/i965/genX_state_upload.c b/src/mesa/drivers/dri/i965/genX_state_upload.c
index bc47e5a16fe..a8641a31768 100644
--- a/src/mesa/drivers/dri/i965/genX_state_upload.c
+++ b/src/mesa/drivers/dri/i965/genX_state_upload.c
@@ -2741,31 +2741,58 @@ UNUSED static const uint32_t push_constant_opcodes[] = {
 };
 
 static void
-upload_constant_state(struct brw_context *brw,
-                      struct brw_stage_state *stage_state,
-                      bool active, uint32_t stage)
+genX(upload_push_constant_packets)(struct brw_context *brw)
 {
    UNUSED uint32_t mocs = GEN_GEN < 8 ? GEN7_MOCS_L3 : 0;
-   active = active && stage_state->push_const_size != 0;
 
-   brw_batch_emit(brw, GENX(3DSTATE_CONSTANT_VS), pkt) {
-      pkt._3DCommandSubOpcode = push_constant_opcodes[stage];
-      if (active) {
+   struct brw_stage_state *stage_states[] = {
+      &brw->vs.base,
+      &brw->tcs.base,
+      &brw->tes.base,
+      &brw->gs.base,
+      &brw->wm.base,
+   };
+
+   if (GEN_GEN == 7 && !GEN_IS_HASWELL && !brw->is_baytrail &&
+       stage_states[MESA_SHADER_VERTEX]->push_constants_dirty)
+      gen7_emit_vs_workaround_flush(brw);
+
+   for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {
+      struct brw_stage_state *stage_state = stage_states[stage];
+      bool active = stage_state->prog_data && stage_state->push_const_size > 0;
+
+      if (!stage_state->push_constants_dirty)
+         continue;
+
+      brw_batch_emit(brw, GENX(3DSTATE_CONSTANT_VS), pkt) {
+         pkt._3DCommandSubOpcode = push_constant_opcodes[stage];
+         if (active) {
 #if GEN_GEN >= 8 || GEN_IS_HASWELL
-         pkt.ConstantBody.ReadLength[2] = stage_state->push_const_size;
-         pkt.ConstantBody.Buffer[2] =
-            render_ro_bo(stage_state->push_const_bo,
-                         stage_state->push_const_offset);
+            pkt.ConstantBody.ReadLength[2] = stage_state->push_const_size;
+            pkt.ConstantBody.Buffer[2] =
+               render_ro_bo(stage_state->push_const_bo,
+                            stage_state->push_const_offset);
 #else
-         pkt.ConstantBody.ReadLength[0] = stage_state->push_const_size;
-         pkt.ConstantBody.Buffer[0].offset =
-            stage_state->push_const_offset | mocs;
+            pkt.ConstantBody.ReadLength[0] = stage_state->push_const_size;
+            pkt.ConstantBody.Buffer[0].offset =
+               stage_state->push_const_offset | mocs;
 #endif
+         }
       }
+
+      stage_state->push_constants_dirty = false;
    }
 
    brw->ctx.NewDriverState |= GEN_GEN >= 9 ? BRW_NEW_SURFACES : 0;
 }
+
+const struct brw_tracked_state genX(push_constant_packets) = {
+   .dirty = {
+      .mesa  = 0,
+      .brw   = BRW_NEW_DRAW_CALL,
+   },
+   .emit = genX(upload_push_constant_packets),
+};
 #endif
 
 #if GEN_GEN >= 6
@@ -2781,14 +2808,6 @@ genX(upload_vs_push_constants)(struct brw_context *brw)
 
    _mesa_shader_write_subroutine_indices(&brw->ctx, MESA_SHADER_VERTEX);
    gen6_upload_push_constants(brw, &vp->program, prog_data, stage_state);
-
-#if GEN_GEN >= 7
-   if (GEN_GEN == 7 && !GEN_IS_HASWELL && !brw->is_baytrail)
-      gen7_emit_vs_workaround_flush(brw);
-
-   upload_constant_state(brw, stage_state, true /* active */,
-                         MESA_SHADER_VERTEX);
-#endif
 }
 
 static const struct brw_tracked_state genX(vs_push_constants) = {
@@ -2819,10 +2838,6 @@ genX(upload_gs_push_constants)(struct brw_context *brw)
       _mesa_shader_write_subroutine_indices(&brw->ctx, MESA_SHADER_GEOMETRY);
       gen6_upload_push_constants(brw, &gp->program, prog_data, stage_state);
    }
-
-#if GEN_GEN >= 7
-   upload_constant_state(brw, stage_state, gp, MESA_SHADER_GEOMETRY);
-#endif
 }
 
 static const struct brw_tracked_state genX(gs_push_constants) = {
@@ -2850,10 +2865,6 @@ genX(upload_wm_push_constants)(struct brw_context *brw)
    _mesa_shader_write_subroutine_indices(&brw->ctx, MESA_SHADER_FRAGMENT);
 
    gen6_upload_push_constants(brw, &fp->program, prog_data, stage_state);
-
-#if GEN_GEN >= 7
-   upload_constant_state(brw, stage_state, true, MESA_SHADER_FRAGMENT);
-#endif
 }
 
 static const struct brw_tracked_state genX(wm_push_constants) = {
@@ -3672,8 +3683,6 @@ genX(upload_tes_push_constants)(struct brw_context *brw)
       _mesa_shader_write_subroutine_indices(&brw->ctx, MESA_SHADER_TESS_EVAL);
       gen6_upload_push_constants(brw, &tep->program, prog_data, stage_state);
    }
-
-   upload_constant_state(brw, stage_state, tep, MESA_SHADER_TESS_EVAL);
 }
 
 static const struct brw_tracked_state genX(tes_push_constants) = {
@@ -3703,8 +3712,6 @@ genX(upload_tcs_push_constants)(struct brw_context *brw)
       _mesa_shader_write_subroutine_indices(&brw->ctx, MESA_SHADER_TESS_CTRL);
       gen6_upload_push_constants(brw, &tcp->program, prog_data, stage_state);
    }
-
-   upload_constant_state(brw, stage_state, active, MESA_SHADER_TESS_CTRL);
 }
 
 static const struct brw_tracked_state genX(tcs_push_constants) = {
@@ -5047,6 +5054,9 @@ genX(init_atoms)(struct brw_context *brw)
       &gen6_renderbuffer_surfaces,
       &brw_renderbuffer_read_surfaces,
       &brw_texture_surfaces,
+
+      &genX(push_constant_packets),
+
       &brw_vs_binding_table,
       &brw_tcs_binding_table,
       &brw_tes_binding_table,
@@ -5136,6 +5146,9 @@ genX(init_atoms)(struct brw_context *brw)
       &gen6_renderbuffer_surfaces,
       &brw_renderbuffer_read_surfaces,
       &brw_texture_surfaces,
+
+      &genX(push_constant_packets),
+
       &brw_vs_binding_table,
       &brw_tcs_binding_table,
       &brw_tes_binding_table,
-- 
2.13.2



More information about the mesa-dev mailing list