Mesa (master): iris: Rework zeroing of stream output buffer offsets

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Mar 4 22:48:15 UTC 2021


Module: Mesa
Branch: master
Commit: 08e04ddd2c447012460af50a808079451f8754f7
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=08e04ddd2c447012460af50a808079451f8754f7

Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Tue Feb  2 17:02:05 2021 -0800

iris: Rework zeroing of stream output buffer offsets

The previous mechanism was a bit fragile.  We stored the zero offset
in the pre-baked packet, and used an flag to override 0xFFFFFFFF
(append) offsets until our first emit - then prohibited anyone from
trying to re-emit the packet by flagging IRIS_DIRTY_SO_BUFFERS,
because that would re-emit the version with the zeroing of the offset.

Now, we always store 0xFFFFFFFF in the pre-baked packet, and use a
flag to override it to zero on the first emit.  That way, we can
re-emit that packet at any time, and it'll just keep appending.

Reviewed-by: Zoltán Böszörményi <zboszor at gmail.com>
Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8964>

---

 src/gallium/drivers/iris/iris_context.h |  4 ++--
 src/gallium/drivers/iris/iris_draw.c    |  5 +---
 src/gallium/drivers/iris/iris_state.c   | 41 +++++++++++++++++++++++++--------
 3 files changed, 34 insertions(+), 16 deletions(-)

diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h
index ed7affdb352..07da14adf37 100644
--- a/src/gallium/drivers/iris/iris_context.h
+++ b/src/gallium/drivers/iris/iris_context.h
@@ -537,8 +537,8 @@ struct iris_stream_output_target {
    /** Stride (bytes-per-vertex) during this transform feedback operation */
    uint16_t stride;
 
-   /** Has 3DSTATE_SO_BUFFER actually been emitted, zeroing the offsets? */
-   bool zeroed;
+   /** Does the next 3DSTATE_SO_BUFFER need to zero the offsets? */
+   bool zero_offset;
 };
 
 /**
diff --git a/src/gallium/drivers/iris/iris_draw.c b/src/gallium/drivers/iris/iris_draw.c
index 581d306a877..fb29dad27ab 100644
--- a/src/gallium/drivers/iris/iris_draw.c
+++ b/src/gallium/drivers/iris/iris_draw.c
@@ -265,11 +265,8 @@ iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info,
    if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
       return;
 
-   /* We can't safely re-emit 3DSTATE_SO_BUFFERS because it may zero the
-    * write offsets, changing the behavior.
-    */
    if (INTEL_DEBUG & DEBUG_REEMIT) {
-      ice->state.dirty |= IRIS_ALL_DIRTY_FOR_RENDER & ~IRIS_DIRTY_SO_BUFFERS;
+      ice->state.dirty |= IRIS_ALL_DIRTY_FOR_RENDER;
       ice->state.stage_dirty |= IRIS_ALL_STAGE_DIRTY_FOR_RENDER;
    }
 
diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c
index 83d06e97b89..00f03977b54 100644
--- a/src/gallium/drivers/iris/iris_state.c
+++ b/src/gallium/drivers/iris/iris_state.c
@@ -3809,13 +3809,18 @@ iris_set_stream_output_targets(struct pipe_context *ctx,
        */
       assert(offset == 0 || offset == 0xFFFFFFFF);
 
-      /* We might be called by Begin (offset = 0), Pause, then Resume
-       * (offset = 0xFFFFFFFF) before ever drawing (where these commands
-       * will actually be sent to the GPU).  In this case, we don't want
-       * to append - we still want to do our initial zeroing.
+      /* When we're first called with an offset of 0, we want the next
+       * 3DSTATE_SO_BUFFER packets to reset the offset to the beginning.
+       * Any further times we emit those packets, we want to use 0xFFFFFFFF
+       * to continue appending from the current offset.
+       *
+       * Note that we might be called by Begin (offset = 0), Pause, then
+       * Resume (offset = 0xFFFFFFFF) before ever drawing (where these
+       * commands will actually be sent to the GPU).  In this case, we
+       * don't want to append - we still want to do our initial zeroing.
        */
-      if (!tgt->zeroed)
-         offset = 0;
+      if (offset == 0)
+         tgt->zero_offset = true;
 
       iris_pack_command(GENX(3DSTATE_SO_BUFFER), so_buffers, sob) {
 #if GEN_GEN < 12
@@ -3833,10 +3838,10 @@ iris_set_stream_output_targets(struct pipe_context *ctx,
          sob.MOCS = iris_mocs(res->bo, &screen->isl_dev, 0);
 
          sob.SurfaceSize = MAX2(tgt->base.buffer_size / 4, 1) - 1;
-         sob.StreamOffset = offset;
          sob.StreamOutputBufferOffsetAddress =
             rw_bo(NULL, iris_resource_bo(tgt->offset.res)->gtt_offset +
                         tgt->offset.offset, IRIS_DOMAIN_OTHER_WRITE);
+         sob.StreamOffset = 0xFFFFFFFF; /* not offset, see above */
       }
    }
 
@@ -6000,18 +6005,34 @@ iris_upload_dirty_render_state(struct iris_context *ice,
 
    if (ice->state.streamout_active) {
       if (dirty & IRIS_DIRTY_SO_BUFFERS) {
-         iris_batch_emit(batch, genx->so_buffers,
-                         4 * 4 * GENX(3DSTATE_SO_BUFFER_length));
          for (int i = 0; i < 4; i++) {
             struct iris_stream_output_target *tgt =
                (void *) ice->state.so_target[i];
+            const uint32_t dwords = GENX(3DSTATE_SO_BUFFER_length);
+            uint32_t *so_buffers = genx->so_buffers + i * dwords;
+            bool zero_offset = false;
+
             if (tgt) {
-               tgt->zeroed = true;
+               zero_offset = tgt->zero_offset;
                iris_use_pinned_bo(batch, iris_resource_bo(tgt->base.buffer),
                                   true, IRIS_DOMAIN_OTHER_WRITE);
                iris_use_pinned_bo(batch, iris_resource_bo(tgt->offset.res),
                                   true, IRIS_DOMAIN_OTHER_WRITE);
             }
+
+            if (zero_offset) {
+               /* Skip the last DWord which contains "Stream Offset" of
+                * 0xFFFFFFFF and instead emit a dword of zero directly.
+                */
+               STATIC_ASSERT(GENX(3DSTATE_SO_BUFFER_StreamOffset_start) ==
+                             32 * (dwords - 1));
+               const uint32_t zero = 0;
+               iris_batch_emit(batch, so_buffers, 4 * (dwords - 1));
+               iris_batch_emit(batch, &zero, sizeof(zero));
+               tgt->zero_offset = false;
+            } else {
+               iris_batch_emit(batch, so_buffers, 4 * dwords);
+            }
          }
       }
 



More information about the mesa-commit mailing list