[Mesa-dev] [PATCH 06/14] intel/blorp: Add initial support for indirect clear colors
Jason Ekstrand
jason at jlekstrand.net
Mon Nov 13 16:12:46 UTC 2017
---
src/intel/blorp/blorp.c | 1 +
src/intel/blorp/blorp.h | 7 +++
src/intel/blorp/blorp_genX_exec.h | 77 +++++++++++++++++++++++++++++
src/intel/blorp/blorp_priv.h | 1 +
src/intel/vulkan/genX_blorp_exec.c | 10 ++++
src/mesa/drivers/dri/i965/genX_blorp_exec.c | 13 +++++
6 files changed, 109 insertions(+)
diff --git a/src/intel/blorp/blorp.c b/src/intel/blorp/blorp.c
index 5faba75..8a9d2fd 100644
--- a/src/intel/blorp/blorp.c
+++ b/src/intel/blorp/blorp.c
@@ -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 :
diff --git a/src/intel/blorp/blorp.h b/src/intel/blorp/blorp.h
index 9716c66..c3077aa 100644
--- a/src/intel/blorp/blorp.h
+++ b/src/intel/blorp/blorp.h
@@ -106,6 +106,13 @@ 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
+ * this 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
diff --git a/src/intel/blorp/blorp_genX_exec.h b/src/intel/blorp/blorp_genX_exec.h
index 5389262..4f88650 100644
--- a/src/intel/blorp/blorp_genX_exec.h
+++ b/src/intel/blorp/blorp_genX_exec.h
@@ -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,
@@ -1259,6 +1300,20 @@ blorp_emit_surface_state(struct blorp_batch *batch,
}
blorp_flush_range(batch, state, GENX(RENDER_SURFACE_STATE_length) * 4);
+
+#if GEN_GEN > 10
+# error("Implement indirect clear support on gen11+")
+#elif GEN_GEN >= 7 && GEN_GEN <= 10
+ if (surface->clear_color_addr.buffer) {
+ 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
+ /* Indirect clears are only supported on gen7+ */
+ assert(surface->clear_color_addr.buffer == NULL);
+#endif
}
static void
@@ -1303,6 +1358,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 {
@@ -1316,6 +1372,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 =
@@ -1329,9 +1387,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);
diff --git a/src/intel/blorp/blorp_priv.h b/src/intel/blorp/blorp_priv.h
index d91e436..faa0af1 100644
--- a/src/intel/blorp/blorp_priv.h
+++ b/src/intel/blorp/blorp_priv.h
@@ -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;
diff --git a/src/intel/vulkan/genX_blorp_exec.c b/src/intel/vulkan/genX_blorp_exec.c
index f041fc7..817b530 100644
--- a/src/intel/vulkan/genX_blorp_exec.c
+++ b/src/intel/vulkan/genX_blorp_exec.c
@@ -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,
diff --git a/src/mesa/drivers/dri/i965/genX_blorp_exec.c b/src/mesa/drivers/dri/i965/genX_blorp_exec.c
index 3c7a7b4..e47db59 100644
--- a/src/mesa/drivers/dri/i965/genX_blorp_exec.c
+++ b/src/mesa/drivers/dri/i965/genX_blorp_exec.c
@@ -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,
--
2.5.0.400.gff86faf
More information about the mesa-dev
mailing list