[Mesa-dev] [PATCH] [v3] i965: Split out gen8 push constant state upload

Kenneth Graunke kenneth at whitecape.org
Sat Jul 11 10:58:17 PDT 2015


On Thursday, July 09, 2015 11:00:40 AM Ben Widawsky wrote:
> While implementing the workaround in the previous patch I noticed things were
> starting to get a bit messy. Since gen8 works differently enough from gen7, I
> thought splitting it out with be good.

IMHO this is still a bit messy.  What about separating the packet
emission from the decision-making about which of the 4 buffers to use?
Something along these lines (warning: doesn't compile):

#define OUT_RELOC_NULL(x) if (x != 0) { OUT_RELOC(x) } else { OUT_BATCH(x); }
#define OUT_RELOC64_NULL(x) if (x != 0) { OUT_RELOC64(x) } else { OUT_BATCH(x); }

static inline void
emit_3dstate_constant(struct brw_context *brw,
                      uint32_t opcode,
                      uint32_t mocs,
                      uint16_t read_length_0,
                      uint16_t read_length_1,
                      uint16_t read_length_2,
                      uint16_t read_length_3,
                      uint64_t ptr_0,
                      uint64_t ptr_1,
                      uint64_t ptr_2,
                      uint64_t ptr_3)
{
   // XXX: or in mocs wherever it goes
   if (brw->gen >= 8) {
      BEGIN_BATCH(11);
      OUT_BATCH(opcode << 16 | (11 - 2));
      OUT_BATCH(read_length_0 | read_length_1 << 16);
      OUT_BATCH(read_length_2 | read_length_3 << 16);
      OUT_BATCH64(ptr_0);
      OUT_RELOC64_NULL(ptr_1);
      OUT_RELOC64_NULL(ptr_2);
      OUT_RELOC64_NULL(ptr_3);
      ADVANCE_BATCH();
   } else if (brw->gen == 7) {
      /* XXX: we could even put asserts here about the buffers being enabled
       * in order, i.e. if you use 2 you have to use 0 and 1 also
       */
      BEGIN_BATCH(7);
      OUT_BATCH(opcode << 16 | (11 - 2));
      OUT_BATCH(read_length_0 | read_length_1 << 16);
      OUT_BATCH(read_length_2 | read_length_3 << 16);
      OUT_BATCH(ptr_0);
      OUT_RELOC_NULL(ptr_1);
      OUT_RELOC_NULL(ptr_2);
      OUT_RELOC_NULL(ptr_3);
      ADVANCE_BATCH();
   } else if (brw->gen == 6) {
      /* XXX: could probably do gen6 here too */
   } else {
      unreachable("unhandled gen in emit_3dstate_constant");
   }
}

void
gen7_upload_constant_state(struct brw_context *brw,
                           const struct brw_stage_state *stage_state,
                           bool active, unsigned opcode)
{
   uint32_t mocs = brw->gen < 8 ? GEN7_MOCS_L3 : 0;

   /* Disable if the shader stage is inactive or there are no push constants. */
   active = active && stage_state->push_const_size != 0;

   if (!active) {
      emit_3dstate_constant(brw, opcode, mocs, 0, 0, 0, 0, 0, 0, 0, 0);
   } else if (brw->gen >= 9) {
      /* Workaround for SKL+ (we use option #2 until we have a need for more
       * constant buffers). This comes from the documentation for 3DSTATE_CONSTANT_*
       *
       * The driver must ensure The following case does not occur without a flush
       * to the 3D engine: 3DSTATE_CONSTANT_* with buffer 3 read length equal to
       * zero committed followed by a 3DSTATE_CONSTANT_* with buffer 0 read length
       * not equal to zero committed. Possible ways to avoid this condition
       * include:
       *     1. always force buffer 3 to have a non zero read length
       *     2. always force buffer 0 to a zero read length
       */
      emit_3dstate_constant(brw, opcode, mocs,
                            0, stage_state->push_const_size, 0, 0,
                            0, stage_state->push_const_offset, 0, 0);
   } else {
      emit_3dstate_constant(brw, opcode, mocs,
                            stage_state->push_const_size, 0, 0, 0,
                            stage_state->push_const_offset, 0, 0, 0);
   }
   
   /* On SKL+ the new constants don't take effect until the next corresponding
    * 3DSTATE_BINDING_TABLE_POINTER_* command is parsed so we need to ensure
    * that is sent
    */
    if (brw->gen >= 9)
       brw->ctx.NewDriverState |= BRW_NEW_SURFACES;
}

By using a static inline, all the code for unused buffers *should* get
compiled away, seeing as it's all 0.  We might have to stuff it in a .h
file, or put all the gen6+ constbuf stuff in a single file, i.e.
gen6_push_constants.c.

Anyway, just an idea...

--Ken
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20150711/ba72d1ef/attachment.sig>


More information about the mesa-dev mailing list