intel/blorp: Add initial support for indirect clear colors
authorJason Ekstrand <jason.ekstrand@intel.com>
Sat, 11 Nov 2017 19:10:59 +0000 (11:10 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Tue, 28 Nov 2017 00:22:12 +0000 (16:22 -0800)
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
src/intel/blorp/blorp.c
src/intel/blorp/blorp.h
src/intel/blorp/blorp_genX_exec.h
src/intel/blorp/blorp_priv.h
src/intel/vulkan/genX_blorp_exec.c
src/mesa/drivers/dri/i965/genX_blorp_exec.c

index 5faba75b8db9ae82aa8416bb51833e59dcbbcf5a..8a9d2fd3b97e1e6fa12652d4e0fdfffec5ab8547 100644 (file)
@@ -100,6 +100,7 @@ brw_blorp_surface_info_init(struct blorp_context *blorp,
    }
 
    info->clear_color = surf->clear_color;
+   info->clear_color_addr = surf->clear_color_addr;
 
    info->view = (struct isl_view) {
       .usage = is_render_target ? ISL_SURF_USAGE_RENDER_TARGET_BIT :
index 31eb1ece0ffcc977ac0b4c95cfdc101541655d6a..6027076afd0bdfb7a62d19d91c681205320611ef 100644 (file)
@@ -101,6 +101,14 @@ struct blorp_surf
    enum isl_aux_usage aux_usage;
 
    union isl_color_value clear_color;
+
+   /**
+    * If set (bo != NULL), clear_color is ignored and the actual clear color
+    * is fetched from this address.  On gen7-8, this is all of dword 7 of
+    * RENDER_SURFACE_STATE and is the responsibility of the caller to ensure
+    * that it contains a swizzle of RGBA and resource min LOD of 0.
+    */
+   struct blorp_address clear_color_addr;
 };
 
 void
index 3dd4bb76af24414857eaa0579c0ff24bda8aa6e7..1968460be052feaae3fa9ab91e659700dfa6f894 100644 (file)
@@ -78,6 +78,11 @@ static void
 blorp_surface_reloc(struct blorp_batch *batch, uint32_t ss_offset,
                     struct blorp_address address, uint32_t delta);
 
+#if GEN_GEN >= 7
+static struct blorp_address
+blorp_get_surface_base_address(struct blorp_batch *batch);
+#endif
+
 static void
 blorp_emit_urb_config(struct blorp_batch *batch,
                       unsigned vs_entry_size, unsigned sf_entry_size);
@@ -1202,6 +1207,42 @@ blorp_emit_pipeline(struct blorp_batch *batch,
 
 #endif /* GEN_GEN >= 6 */
 
+#if GEN_GEN >= 7 && GEN_GEN <= 10
+static void
+blorp_emit_memcpy(struct blorp_batch *batch,
+                  struct blorp_address dst,
+                  struct blorp_address src,
+                  uint32_t size)
+{
+   assert(size % 4 == 0);
+
+   for (unsigned dw = 0; dw < size; dw += 4) {
+#if GEN_GEN >= 8
+      blorp_emit(batch, GENX(MI_COPY_MEM_MEM), cp) {
+         cp.DestinationMemoryAddress = dst;
+         cp.SourceMemoryAddress = src;
+      }
+#else
+      /* IVB does not have a general purpose register for command streamer
+       * commands. Therefore, we use an alternate temporary register.
+       */
+#define BLORP_TEMP_REG 0x2440 /* GEN7_3DPRIM_BASE_VERTEX */
+      blorp_emit(batch, GENX(MI_LOAD_REGISTER_MEM), load) {
+         load.RegisterAddress = BLORP_TEMP_REG;
+         load.MemoryAddress = src;
+      }
+      blorp_emit(batch, GENX(MI_STORE_REGISTER_MEM), store) {
+         store.RegisterAddress = BLORP_TEMP_REG;
+         store.MemoryAddress = dst;
+      }
+#undef BLORP_TEMP_REG
+#endif
+      dst.offset += 4;
+      src.offset += 4;
+   }
+}
+#endif
+
 static void
 blorp_emit_surface_state(struct blorp_batch *batch,
                          const struct brw_blorp_surface_info *surface,
@@ -1257,6 +1298,19 @@ blorp_emit_surface_state(struct blorp_batch *batch,
    }
 
    blorp_flush_range(batch, state, GENX(RENDER_SURFACE_STATE_length) * 4);
+
+   if (surface->clear_color_addr.buffer) {
+#if GEN_GEN > 10
+      unreachable("Implement indirect clear support on gen11+");
+#elif GEN_GEN >= 7 && GEN_GEN <= 10
+      struct blorp_address dst_addr = blorp_get_surface_base_address(batch);
+      dst_addr.offset += state_offset + isl_dev->ss.clear_value_offset;
+      blorp_emit_memcpy(batch, dst_addr, surface->clear_color_addr,
+                        isl_dev->ss.clear_value_size);
+#else
+      unreachable("Fast clears are only supported on gen7+");
+#endif
+   }
 }
 
 static void
@@ -1301,6 +1355,7 @@ blorp_emit_surface_states(struct blorp_batch *batch,
    uint32_t bind_offset, surface_offsets[2];
    void *surface_maps[2];
 
+   MAYBE_UNUSED bool has_indirect_clear_color = false;
    if (params->use_pre_baked_binding_table) {
       bind_offset = params->pre_baked_binding_table_offset;
    } else {
@@ -1314,6 +1369,8 @@ blorp_emit_surface_states(struct blorp_batch *batch,
                                   surface_maps[BLORP_RENDERBUFFER_BT_INDEX],
                                   surface_offsets[BLORP_RENDERBUFFER_BT_INDEX],
                                   params->color_write_disable, true);
+         if (params->dst.clear_color_addr.buffer != NULL)
+            has_indirect_clear_color = true;
       } else {
          assert(params->depth.enabled || params->stencil.enabled);
          const struct brw_blorp_surface_info *surface =
@@ -1327,9 +1384,28 @@ blorp_emit_surface_states(struct blorp_batch *batch,
                                   surface_maps[BLORP_TEXTURE_BT_INDEX],
                                   surface_offsets[BLORP_TEXTURE_BT_INDEX],
                                   NULL, false);
+         if (params->src.clear_color_addr.buffer != NULL)
+            has_indirect_clear_color = true;
       }
    }
 
+#if GEN_GEN >= 7 && GEN_GEN <= 10
+   if (has_indirect_clear_color) {
+      /* Updating a surface state object may require that the state cache be
+       * invalidated. From the SKL PRM, Shared Functions -> State -> State
+       * Caching:
+       *
+       *    Whenever the RENDER_SURFACE_STATE object in memory pointed to by
+       *    the Binding Table Pointer (BTP) and Binding Table Index (BTI) is
+       *    modified [...], the L1 state cache must be invalidated to ensure
+       *    the new surface or sampler state is fetched from system memory.
+       */
+      blorp_emit(batch, GENX(PIPE_CONTROL), pipe) {
+         pipe.StateCacheInvalidationEnable = true;
+      }
+   }
+#endif
+
 #if GEN_GEN >= 7
    blorp_emit(batch, GENX(3DSTATE_BINDING_TABLE_POINTERS_VS), bt);
    blorp_emit(batch, GENX(3DSTATE_BINDING_TABLE_POINTERS_HS), bt);
index d91e436c1c57144fc4b1711c6b7efacea99391b9..faa0af10d4a7f39c4e4b4b679be26f6da6b8d188 100644 (file)
@@ -56,6 +56,7 @@ struct brw_blorp_surface_info
    enum isl_aux_usage aux_usage;
 
    union isl_color_value clear_color;
+   struct blorp_address clear_color_addr;
 
    struct isl_view view;
 
index b4b05c7022a98008ed28cfa30297dc14bf279fe0..e849a3b8e3e2f7e1049c22b72496a60bfb53ce0a 100644 (file)
@@ -64,6 +64,16 @@ blorp_surface_reloc(struct blorp_batch *batch, uint32_t ss_offset,
       anv_batch_set_error(&cmd_buffer->batch, result);
 }
 
+static struct blorp_address
+blorp_get_surface_base_address(struct blorp_batch *batch)
+{
+   struct anv_cmd_buffer *cmd_buffer = batch->driver_batch;
+   return (struct blorp_address) {
+      .buffer = &cmd_buffer->device->surface_state_pool.block_pool.bo,
+      .offset = 0,
+   };
+}
+
 static void *
 blorp_alloc_dynamic_state(struct blorp_batch *batch,
                           uint32_t size,
index f824c127e4062f472aa4383e8d325ce58902a8bb..87e90fde91c80324519025d059372171bc7ca8b8 100644 (file)
@@ -94,6 +94,19 @@ blorp_surface_reloc(struct blorp_batch *batch, uint32_t ss_offset,
 #endif
 }
 
+#if GEN_GEN >= 7
+static struct blorp_address
+blorp_get_surface_base_address(struct blorp_batch *batch)
+{
+   assert(batch->blorp->driver_ctx == batch->driver_batch);
+   struct brw_context *brw = batch->driver_batch;
+   return (struct blorp_address) {
+      .buffer = brw->batch.state_bo,
+      .offset = 0,
+   };
+}
+#endif
+
 static void *
 blorp_alloc_dynamic_state(struct blorp_batch *batch,
                           uint32_t size,