iris: Invalidate state/texture/constant caches after STATE_BASE_ADDRESS
authorKenneth Graunke <kenneth@whitecape.org>
Tue, 3 Sep 2019 22:34:54 +0000 (15:34 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Fri, 6 Sep 2019 17:57:55 +0000 (10:57 -0700)
Jason pointed out that the caches likely refer to offsets from dynamic
and surface state base addresses, so when we change those, we need to
invalidate the caches.

Comment borrowed from src/intel/vulkan/genX_cmd_buffer.c.

src/gallium/drivers/iris/iris_state.c

index 19e795355c0e9f02e4e0a0294778c264b46a3d1d..525263174e05513b26406c7d1f0cec4960be88f2 100644 (file)
@@ -391,7 +391,7 @@ emit_state(struct iris_batch *batch,
    (!old_cso || memcmp(old_cso->x, new_cso->x, sizeof(old_cso->x)) != 0)
 
 static void
-flush_for_state_base_change(struct iris_batch *batch)
+flush_before_state_base_change(struct iris_batch *batch)
 {
    /* Flush before emitting STATE_BASE_ADDRESS.
     *
@@ -415,12 +415,59 @@ flush_for_state_base_change(struct iris_batch *batch)
     * rendering.  It's a bit of a big hammer but it appears to work.
     */
    iris_emit_end_of_pipe_sync(batch,
-                              "change STATE_BASE_ADDRESS",
+                              "change STATE_BASE_ADDRESS (flushes)",
                               PIPE_CONTROL_RENDER_TARGET_FLUSH |
                               PIPE_CONTROL_DEPTH_CACHE_FLUSH |
                               PIPE_CONTROL_DATA_CACHE_FLUSH);
 }
 
+static void
+flush_after_state_base_change(struct iris_batch *batch)
+{
+   /* After re-setting the surface state base address, we have to do some
+    * cache flusing so that the sampler engine will pick up the new
+    * SURFACE_STATE objects and binding tables. From the Broadwell PRM,
+    * Shared Function > 3D Sampler > State > State Caching (page 96):
+    *
+    *    Coherency with system memory in the state cache, like the texture
+    *    cache is handled partially by software. It is expected that the
+    *    command stream or shader will issue Cache Flush operation or
+    *    Cache_Flush sampler message to ensure that the L1 cache remains
+    *    coherent with system memory.
+    *
+    *    [...]
+    *
+    *    Whenever the value of the Dynamic_State_Base_Addr,
+    *    Surface_State_Base_Addr are altered, the L1 state cache must be
+    *    invalidated to ensure the new surface or sampler state is fetched
+    *    from system memory.
+    *
+    * The PIPE_CONTROL command has a "State Cache Invalidation Enable" bit
+    * which, according the PIPE_CONTROL instruction documentation in the
+    * Broadwell PRM:
+    *
+    *    Setting this bit is independent of any other bit in this packet.
+    *    This bit controls the invalidation of the L1 and L2 state caches
+    *    at the top of the pipe i.e. at the parsing time.
+    *
+    * Unfortunately, experimentation seems to indicate that state cache
+    * invalidation through a PIPE_CONTROL does nothing whatsoever in
+    * regards to surface state and binding tables.  In stead, it seems that
+    * invalidating the texture cache is what is actually needed.
+    *
+    * XXX:  As far as we have been able to determine through
+    * experimentation, shows that flush the texture cache appears to be
+    * sufficient.  The theory here is that all of the sampling/rendering
+    * units cache the binding table in the texture cache.  However, we have
+    * yet to be able to actually confirm this.
+    */
+   iris_emit_end_of_pipe_sync(batch,
+                              "change STATE_BASE_ADDRESS (invalidates)",
+                              PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
+                              PIPE_CONTROL_CONST_CACHE_INVALIDATE |
+                              PIPE_CONTROL_STATE_CACHE_INVALIDATE);
+}
+
 static void
 _iris_emit_lri(struct iris_batch *batch, uint32_t reg, uint32_t val)
 {
@@ -513,7 +560,7 @@ init_glk_barrier_mode(struct iris_batch *batch, uint32_t value)
 static void
 init_state_base_address(struct iris_batch *batch)
 {
-   flush_for_state_base_change(batch);
+   flush_before_state_base_change(batch);
 
    /* We program most base addresses once at context initialization time.
     * Each base address points at a 4GB memory zone, and never needs to
@@ -551,6 +598,8 @@ init_state_base_address(struct iris_batch *batch)
       sba.InstructionBufferSize    = 0xfffff;
       sba.DynamicStateBufferSize   = 0xfffff;
    }
+
+   flush_after_state_base_change(batch);
 }
 
 static void
@@ -4568,7 +4617,7 @@ iris_update_surface_base_address(struct iris_batch *batch,
    if (batch->last_surface_base_address == binder->bo->gtt_offset)
       return;
 
-   flush_for_state_base_change(batch);
+   flush_before_state_base_change(batch);
 
    iris_emit_cmd(batch, GENX(STATE_BASE_ADDRESS), sba) {
       sba.SurfaceStateBaseAddressModifyEnable = true;
@@ -4588,6 +4637,8 @@ iris_update_surface_base_address(struct iris_batch *batch,
 #endif
    }
 
+   flush_after_state_base_change(batch);
+
    batch->last_surface_base_address = binder->bo->gtt_offset;
 }