--- 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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev