iris: rewrite set_vertex_buffer and VB handling
authorKenneth Graunke <kenneth@whitecape.org>
Wed, 5 Dec 2018 00:38:14 +0000 (16:38 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Thu, 21 Feb 2019 18:26:10 +0000 (10:26 -0800)
I was using the Gallium API wrong.  set_* functions with start_slot
and count parameters are supposed to update a subrange of the items.
I had been trashing all bound vertex buffers and starting over.

This should hopefully also make it easier to slot in additional
VERTEX_BUFFER_STATEs at draw time, say, for shader draw parameters.

src/gallium/drivers/iris/iris_context.h
src/gallium/drivers/iris/iris_state.c

index 1eedd5d7100f10fa1775f492da556ade1bb7f8f6..d3ccc920eb15cc26b8fab85080fd41f58aa5c7b2 100644 (file)
@@ -454,6 +454,9 @@ struct iris_context {
       float default_outer_level[4];
       float default_inner_level[2];
 
+      /** Bitfield of which vertex buffers are bound (non-null). */
+      uint64_t bound_vertex_buffers;
+
       bool primitive_restart;
       unsigned cut_index;
       enum pipe_prim_type prim_mode:8;
index d41cb7490b4dd3c882c1a3099ed9fff8bb325874..540f0dfa96db52758a9606cee9ec6779ab3db74a 100644 (file)
@@ -740,14 +740,11 @@ iris_init_compute_context(struct iris_screen *screen,
 }
 
 struct iris_vertex_buffer_state {
-   /** The 3DSTATE_VERTEX_BUFFERS hardware packet. */
-   uint32_t vertex_buffers[1 + 33 * GENX(VERTEX_BUFFER_STATE_length)];
+   /** The VERTEX_BUFFER_STATE hardware structure. */
+   uint32_t state[GENX(VERTEX_BUFFER_STATE_length)];
 
    /** The resource to source vertex data from. */
-   struct pipe_resource *resources[33];
-
-   /** The number of bound vertex buffers. */
-   unsigned num_buffers;
+   struct pipe_resource *resource;
 };
 
 struct iris_depth_buffer_state {
@@ -765,7 +762,11 @@ struct iris_depth_buffer_state {
  * packets which vary by generation.
  */
 struct iris_genx_state {
-   struct iris_vertex_buffer_state vertex_buffers;
+   struct iris_vertex_buffer_state vertex_buffers[33];
+
+   /** The number of bound vertex buffers. */
+   uint64_t bound_vertex_buffers;
+
    struct iris_depth_buffer_state depth_buffer;
 
    uint32_t so_buffers[4 * GENX(3DSTATE_SO_BUFFER_length)];
@@ -2335,13 +2336,6 @@ iris_delete_state(struct pipe_context *ctx, void *state)
    free(state);
 }
 
-static void
-iris_free_vertex_buffers(struct iris_vertex_buffer_state *cso)
-{
-   for (unsigned i = 0; i < cso->num_buffers; i++)
-      pipe_resource_reference(&cso->resources[i], NULL);
-}
-
 /**
  * The pipe->set_vertex_buffers() driver hook.
  *
@@ -2353,53 +2347,43 @@ iris_set_vertex_buffers(struct pipe_context *ctx,
                         const struct pipe_vertex_buffer *buffers)
 {
    struct iris_context *ice = (struct iris_context *) ctx;
-   struct iris_vertex_buffer_state *cso = &ice->state.genx->vertex_buffers;
-
-   iris_free_vertex_buffers(&ice->state.genx->vertex_buffers);
-
-   if (!buffers)
-      count = 0;
-
-   cso->num_buffers = count;
+   struct iris_genx_state *genx = ice->state.genx;
 
-   iris_pack_command(GENX(3DSTATE_VERTEX_BUFFERS), cso->vertex_buffers, vb) {
-      vb.DWordLength = 4 * MAX2(cso->num_buffers, 1) - 1;
-   }
+   ice->state.bound_vertex_buffers &= ~u_bit_consecutive64(start_slot, count);
 
-   uint32_t *vb_pack_dest = &cso->vertex_buffers[1];
+   for (unsigned i = 0; i < count; i++) {
+      const struct pipe_vertex_buffer *buffer = buffers ? &buffers[i] : NULL;
+      struct iris_vertex_buffer_state *state =
+         &genx->vertex_buffers[start_slot + i];
 
-   if (count == 0) {
-      iris_pack_state(GENX(VERTEX_BUFFER_STATE), vb_pack_dest, vb) {
-         vb.VertexBufferIndex = start_slot;
-         vb.NullVertexBuffer = true;
-         vb.AddressModifyEnable = true;
+      if (!buffer) {
+         pipe_resource_reference(&state->resource, NULL);
+         continue;
       }
-   }
 
-   for (unsigned i = 0; i < count; i++) {
-      assert(!buffers[i].is_user_buffer);
+      assert(!buffer->is_user_buffer);
 
-      pipe_resource_reference(&cso->resources[i], buffers[i].buffer.resource);
-      struct iris_resource *res = (void *) cso->resources[i];
+      ice->state.bound_vertex_buffers |= 1ull << (start_slot + i);
+
+      pipe_resource_reference(&state->resource, buffer->buffer.resource);
+      struct iris_resource *res = (void *) state->resource;
 
       if (res)
          res->bind_history |= PIPE_BIND_VERTEX_BUFFER;
 
-      iris_pack_state(GENX(VERTEX_BUFFER_STATE), vb_pack_dest, vb) {
+      iris_pack_state(GENX(VERTEX_BUFFER_STATE), state->state, vb) {
          vb.VertexBufferIndex = start_slot + i;
          vb.MOCS = MOCS_WB;
          vb.AddressModifyEnable = true;
-         vb.BufferPitch = buffers[i].stride;
+         vb.BufferPitch = buffer->stride;
          if (res) {
             vb.BufferSize = res->bo->size;
             vb.BufferStartingAddress =
-               ro_bo(NULL, res->bo->gtt_offset + buffers[i].buffer_offset);
+               ro_bo(NULL, res->bo->gtt_offset + buffer->buffer_offset);
          } else {
             vb.NullVertexBuffer = true;
          }
       }
-
-      vb_pack_dest += GENX(VERTEX_BUFFER_STATE_length);
    }
 
    ice->state.dirty |= IRIS_DIRTY_VERTEX_BUFFERS;
@@ -3739,6 +3723,8 @@ iris_restore_render_saved_bos(struct iris_context *ice,
                               struct iris_batch *batch,
                               const struct pipe_draw_info *draw)
 {
+   struct iris_genx_state *genx = ice->state.genx;
+
    // XXX: whack IRIS_SHADER_DIRTY_BINDING_TABLE on new batch
 
    const uint64_t clean = ~ice->state.dirty;
@@ -3854,10 +3840,11 @@ iris_restore_render_saved_bos(struct iris_context *ice,
    }
 
    if (clean & IRIS_DIRTY_VERTEX_BUFFERS) {
-      struct iris_vertex_buffer_state *cso = &ice->state.genx->vertex_buffers;
-      for (unsigned i = 0; i < cso->num_buffers; i++) {
-         struct iris_resource *res = (void *) cso->resources[i];
-         iris_use_pinned_bo(batch, res->bo, false);
+      uint64_t bound = ice->state.bound_vertex_buffers;
+      while (bound) {
+         const int i = u_bit_scan64(&bound);
+         struct pipe_resource *res = genx->vertex_buffers[i].resource;
+         iris_use_pinned_bo(batch, iris_resource_bo(res), false);
       }
    }
 }
@@ -4416,10 +4403,9 @@ iris_upload_dirty_render_state(struct iris_context *ice,
    }
 
    if (dirty & IRIS_DIRTY_VERTEX_BUFFERS) {
-      struct iris_vertex_buffer_state *cso = &ice->state.genx->vertex_buffers;
-      const unsigned vb_dwords = GENX(VERTEX_BUFFER_STATE_length);
+      int count = util_bitcount64(ice->state.bound_vertex_buffers);
 
-      if (cso->num_buffers > 0) {
+      if (count) {
          /* The VF cache designers cut corners, and made the cache key's
           * <VertexBufferIndex, Memory Address> tuple only consider the bottom
           * 32 bits of the address.  If you have two vertex buffers which get
@@ -4431,10 +4417,13 @@ iris_upload_dirty_render_state(struct iris_context *ice,
           */
          unsigned flush_flags = 0;
 
-         for (unsigned i = 0; i < cso->num_buffers; i++) {
+         uint64_t bound = ice->state.bound_vertex_buffers;
+         while (bound) {
+            const int i = u_bit_scan64(&bound);
             uint16_t high_bits = 0;
 
-            struct iris_resource *res = (void *) cso->resources[i];
+            struct iris_resource *res =
+               (void *) genx->vertex_buffers[i].resource;
             if (res) {
                iris_use_pinned_bo(batch, res->bo, false);
 
@@ -4458,8 +4447,22 @@ iris_upload_dirty_render_state(struct iris_context *ice,
          if (flush_flags)
             iris_emit_pipe_control_flush(batch, flush_flags);
 
-         iris_batch_emit(batch, cso->vertex_buffers, sizeof(uint32_t) *
-                         (1 + vb_dwords * cso->num_buffers));
+         const unsigned vb_dwords = GENX(VERTEX_BUFFER_STATE_length);
+
+         uint32_t *map =
+            iris_get_command_space(batch, 4 * (1 + vb_dwords * count));
+         _iris_pack_command(batch, GENX(3DSTATE_VERTEX_BUFFERS), map, vb) {
+            vb.DWordLength = (vb_dwords * count + 1) - 2;
+         }
+         map += 1;
+
+         bound = ice->state.bound_vertex_buffers;
+         while (bound) {
+            const int i = u_bit_scan64(&bound);
+            memcpy(map, genx->vertex_buffers[i].state,
+                   sizeof(uint32_t) * vb_dwords);
+            map += vb_dwords;
+         }
       }
    }
 
@@ -4798,7 +4801,13 @@ iris_upload_compute_state(struct iris_context *ice,
 static void
 iris_destroy_state(struct iris_context *ice)
 {
-   iris_free_vertex_buffers(&ice->state.genx->vertex_buffers);
+   struct iris_genx_state *genx = ice->state.genx;
+
+   uint64_t bound_vbs = ice->state.bound_vertex_buffers;
+   while (bound_vbs) {
+      const int i = u_bit_scan64(&bound_vbs);
+      pipe_resource_reference(&genx->vertex_buffers[i].resource, NULL);
+   }
 
    // XXX: unreference resources/surfaces.
    for (unsigned i = 0; i < ice->state.framebuffer.nr_cbufs; i++) {