From a147ccaa5cf4988408e127fc36d4a851187fd1ab Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Mon, 25 Mar 2024 11:27:01 +0200 Subject: [PATCH] blorp: add support for cached dynamic states MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Of the dynamic states we have blorp reemit for each operations, a few actually never change : * BLEND_STATE (it looks like it does, but actually for anv no) * COLOR_CALC_STATE * CC_VIEWPORT * SAMPLER_STATE We add infrastructure here to upload into the driver and retrieve the state offset later. Signed-off-by: Lionel Landwerlin Reviewed-by: Tapani Pälli Part-of: --- src/gallium/drivers/iris/iris_blorp.c | 7 ++ src/intel/blorp/blorp.h | 28 ++++- src/intel/blorp/blorp_genX_exec_brw.h | 155 +++++++++++++++++++++----- src/intel/vulkan/genX_blorp_exec.c | 7 ++ 4 files changed, 162 insertions(+), 35 deletions(-) diff --git a/src/gallium/drivers/iris/iris_blorp.c b/src/gallium/drivers/iris/iris_blorp.c index 7b2adfd910a..0669c8caa64 100644 --- a/src/gallium/drivers/iris/iris_blorp.c +++ b/src/gallium/drivers/iris/iris_blorp.c @@ -134,6 +134,13 @@ blorp_get_surface_base_address(UNUSED struct blorp_batch *blorp_batch) return (struct blorp_address) { .offset = IRIS_MEMZONE_BINDER_START }; } +static uint32_t +blorp_get_dynamic_state(struct blorp_batch *batch, + enum blorp_dynamic_state name) +{ + unreachable("Not implemented"); +} + static void * blorp_alloc_dynamic_state(struct blorp_batch *blorp_batch, uint32_t size, diff --git a/src/intel/blorp/blorp.h b/src/intel/blorp/blorp.h index 99cf45ac954..1ef463ef395 100644 --- a/src/intel/blorp/blorp.h +++ b/src/intel/blorp/blorp.h @@ -59,6 +59,16 @@ struct blorp_params; struct blorp_config { bool use_mesh_shading; bool use_unrestricted_depth_range; + bool use_cached_dynamic_states; +}; + +enum blorp_dynamic_state { + BLORP_DYNAMIC_STATE_BLEND, + BLORP_DYNAMIC_STATE_CC_VIEWPORT, + BLORP_DYNAMIC_STATE_COLOR_CALC, + BLORP_DYNAMIC_STATE_SAMPLER, + + BLORP_DYNAMIC_STATE_COUNT, }; struct blorp_context { @@ -70,6 +80,11 @@ struct blorp_context { bool enable_tbimr; + void (*upload_dynamic_state)(struct blorp_context *context, + const void *data, uint32_t size, + uint32_t alignment, + enum blorp_dynamic_state name); + bool (*lookup_shader)(struct blorp_batch *batch, const void *key, uint32_t key_size, uint32_t *kernel_out, void *prog_data_out); @@ -103,23 +118,26 @@ enum blorp_batch_flags { * and stencil images passed in will match what is currently set in the * hardware. */ - BLORP_BATCH_NO_EMIT_DEPTH_STENCIL = (1 << 0), + BLORP_BATCH_NO_EMIT_DEPTH_STENCIL = BITFIELD_BIT(0), /* This flag indicates that the blorp call should be predicated. */ - BLORP_BATCH_PREDICATE_ENABLE = (1 << 1), + BLORP_BATCH_PREDICATE_ENABLE = BITFIELD_BIT(1), /* This flag indicates that blorp should *not* update the indirect clear * color buffer. */ - BLORP_BATCH_NO_UPDATE_CLEAR_COLOR = (1 << 2), + BLORP_BATCH_NO_UPDATE_CLEAR_COLOR = BITFIELD_BIT(2), /* This flag indicates that blorp should use a compute program for the * operation. */ - BLORP_BATCH_USE_COMPUTE = (1 << 3), + BLORP_BATCH_USE_COMPUTE = BITFIELD_BIT(3), /** Use the hardware blitter to perform any operations in this batch */ - BLORP_BATCH_USE_BLITTER = (1 << 4), + BLORP_BATCH_USE_BLITTER = BITFIELD_BIT(4), + + /** Reuse dynamic states */ + BLORP_BATCH_REUSE_DYNAMIC_STATES = BITFIELD_BIT(5), }; struct blorp_batch { diff --git a/src/intel/blorp/blorp_genX_exec_brw.h b/src/intel/blorp/blorp_genX_exec_brw.h index 751d4f31eba..6c435e9bbde 100644 --- a/src/intel/blorp/blorp_genX_exec_brw.h +++ b/src/intel/blorp/blorp_genX_exec_brw.h @@ -73,6 +73,10 @@ blorp_alloc_general_state(struct blorp_batch *batch, uint32_t alignment, uint32_t *offset); +static uint32_t +blorp_get_dynamic_state(struct blorp_batch *batch, + enum blorp_dynamic_state name); + static void * blorp_alloc_vertex_buffer(struct blorp_batch *batch, uint32_t size, struct blorp_address *addr); @@ -193,7 +197,20 @@ _blorp_combine_address(struct blorp_batch *batch, void *location, #define STRUCT_ZERO(S) ({ struct S t; memset(&t, 0, sizeof(t)); t; }) -#define blorp_emit_dynamic(batch, state, name, align, offset) \ +#define blorp_context_upload_dynamic(context, state, name, \ + align, dynamic_name) \ + for (struct state name = STRUCT_ZERO(state), *_dst = &name; \ + _dst != NULL; \ + ({ \ + uint32_t _dw[_blorp_cmd_length(state)]; \ + _blorp_cmd_pack(state)(NULL, (void *)_dw, &name); \ + context->upload_dynamic_state(context, _dw, \ + _blorp_cmd_length(state) * 4, \ + align, dynamic_name); \ + _dst = NULL; \ + })) + +#define blorp_emit_dynamic(batch, state, name, align, offset) \ for (struct state name = STRUCT_ZERO(state), \ *_dst = blorp_alloc_dynamic_state(batch, \ _blorp_cmd_length(state) * 4, \ @@ -574,11 +591,16 @@ static uint32_t blorp_emit_cc_viewport(struct blorp_batch *batch) { uint32_t cc_vp_offset; - blorp_emit_dynamic(batch, GENX(CC_VIEWPORT), vp, 32, &cc_vp_offset) { - vp.MinimumDepth = batch->blorp->config.use_unrestricted_depth_range ? + + if (batch->blorp->config.use_cached_dynamic_states) { + cc_vp_offset = blorp_get_dynamic_state(batch, BLORP_DYNAMIC_STATE_CC_VIEWPORT); + } else { + blorp_emit_dynamic(batch, GENX(CC_VIEWPORT), vp, 32, &cc_vp_offset) { + vp.MinimumDepth = batch->blorp->config.use_unrestricted_depth_range ? -FLT_MAX : 0.0; - vp.MaximumDepth = batch->blorp->config.use_unrestricted_depth_range ? + vp.MaximumDepth = batch->blorp->config.use_unrestricted_depth_range ? FLT_MAX : 1.0; + } } blorp_emit(batch, GENX(3DSTATE_VIEWPORT_STATE_POINTERS_CC), vsp) { @@ -617,7 +639,9 @@ blorp_emit_sampler_state(struct blorp_batch *batch) UNUSED static uint32_t blorp_emit_sampler_state_ps(struct blorp_batch *batch) { - uint32_t offset = blorp_emit_sampler_state(batch); + uint32_t offset = batch->blorp->config.use_cached_dynamic_states ? + blorp_get_dynamic_state(batch, BLORP_DYNAMIC_STATE_SAMPLER) : + blorp_emit_sampler_state(batch); blorp_emit(batch, GENX(3DSTATE_SAMPLER_STATE_POINTERS_PS), ssp) { ssp.PointertoPSSamplerState = offset; @@ -858,36 +882,42 @@ static void blorp_emit_blend_state(struct blorp_batch *batch, const struct blorp_params *params) { - struct GENX(BLEND_STATE) blend = { }; - uint32_t offset; - int size = GENX(BLEND_STATE_length) * 4; - size += GENX(BLEND_STATE_ENTRY_length) * 4 * params->num_draw_buffers; - uint32_t *state = blorp_alloc_dynamic_state(batch, size, 64, &offset); - if (state == NULL) - return; - uint32_t *pos = state; + if (!batch->blorp->config.use_cached_dynamic_states) { + struct GENX(BLEND_STATE) blend = { }; - GENX(BLEND_STATE_pack)(NULL, pos, &blend); - pos += GENX(BLEND_STATE_length); + int size = GENX(BLEND_STATE_length) * 4; + size += GENX(BLEND_STATE_ENTRY_length) * 4 * params->num_draw_buffers; + uint32_t *state = blorp_alloc_dynamic_state(batch, size, 64, &offset); + if (state == NULL) + return; + uint32_t *pos = state; - for (unsigned i = 0; i < params->num_draw_buffers; ++i) { - struct GENX(BLEND_STATE_ENTRY) entry = { - .PreBlendColorClampEnable = true, - .PostBlendColorClampEnable = true, - .ColorClampRange = COLORCLAMP_RTFORMAT, + GENX(BLEND_STATE_pack)(NULL, pos, &blend); + pos += GENX(BLEND_STATE_length); - .WriteDisableRed = params->color_write_disable & 1, - .WriteDisableGreen = params->color_write_disable & 2, - .WriteDisableBlue = params->color_write_disable & 4, - .WriteDisableAlpha = params->color_write_disable & 8, - }; - GENX(BLEND_STATE_ENTRY_pack)(NULL, pos, &entry); - pos += GENX(BLEND_STATE_ENTRY_length); + for (unsigned i = 0; i < params->num_draw_buffers; ++i) { + struct GENX(BLEND_STATE_ENTRY) entry = { + .PreBlendColorClampEnable = true, + .PostBlendColorClampEnable = true, + .ColorClampRange = COLORCLAMP_RTFORMAT, + + .WriteDisableRed = params->color_write_disable & 1, + .WriteDisableGreen = params->color_write_disable & 2, + .WriteDisableBlue = params->color_write_disable & 4, + .WriteDisableAlpha = params->color_write_disable & 8, + }; + GENX(BLEND_STATE_ENTRY_pack)(NULL, pos, &entry); + pos += GENX(BLEND_STATE_ENTRY_length); + } + + blorp_flush_range(batch, state, size); + } else { + /* We only cached this case. */ + assert(params->color_write_disable == 0); + offset = blorp_get_dynamic_state(batch, BLORP_DYNAMIC_STATE_BLEND); } - blorp_flush_range(batch, state, size); - blorp_emit(batch, GENX(3DSTATE_BLEND_STATE_POINTERS), sp) { sp.BlendStatePointer = offset; sp.BlendStatePointerValid = true; @@ -903,7 +933,11 @@ blorp_emit_color_calc_state(struct blorp_batch *batch, UNUSED const struct blorp_params *params) { uint32_t offset; - blorp_emit_dynamic(batch, GENX(COLOR_CALC_STATE), cc, 64, &offset) {} + + if (batch->blorp->config.use_cached_dynamic_states) + offset = blorp_get_dynamic_state(batch, BLORP_DYNAMIC_STATE_COLOR_CALC); + else + blorp_emit_dynamic(batch, GENX(COLOR_CALC_STATE), cc, 64, &offset) {} blorp_emit(batch, GENX(3DSTATE_CC_STATE_POINTERS), sp) { sp.ColorCalcStatePointer = offset; @@ -2151,4 +2185,65 @@ blorp_exec(struct blorp_batch *batch, const struct blorp_params *params) } } +static void +blorp_init_dynamic_states(struct blorp_context *context) +{ + { + struct GENX(BLEND_STATE) blend = { }; + + uint32_t dws[GENX(BLEND_STATE_length) * 4 + + GENX(BLEND_STATE_ENTRY_length) * 4 * 8 /* MAX_RTS */]; + uint32_t *pos = dws; + + GENX(BLEND_STATE_pack)(NULL, pos, &blend); + pos += GENX(BLEND_STATE_length); + + for (unsigned i = 0; i < 8; ++i) { + struct GENX(BLEND_STATE_ENTRY) entry = { + .PreBlendColorClampEnable = true, + .PostBlendColorClampEnable = true, + .ColorClampRange = COLORCLAMP_RTFORMAT, + }; + GENX(BLEND_STATE_ENTRY_pack)(NULL, pos, &entry); + pos += GENX(BLEND_STATE_ENTRY_length); + } + + context->upload_dynamic_state(context, dws, sizeof(dws), 64, + BLORP_DYNAMIC_STATE_BLEND); + } + + blorp_context_upload_dynamic(context, GENX(CC_VIEWPORT), vp, 32, + BLORP_DYNAMIC_STATE_CC_VIEWPORT) { + vp.MinimumDepth = context->config.use_unrestricted_depth_range ? + -FLT_MAX : 0.0; + vp.MaximumDepth = context->config.use_unrestricted_depth_range ? + FLT_MAX : 1.0; + } + + blorp_context_upload_dynamic(context, GENX(COLOR_CALC_STATE), cc, 64, + BLORP_DYNAMIC_STATE_COLOR_CALC) { + /* Nothing */ + } + + blorp_context_upload_dynamic(context, GENX(SAMPLER_STATE), sampler, 32, + BLORP_DYNAMIC_STATE_SAMPLER) { + sampler.MipModeFilter = MIPFILTER_NONE; + sampler.MagModeFilter = MAPFILTER_LINEAR; + sampler.MinModeFilter = MAPFILTER_LINEAR; + sampler.MinLOD = 0; + sampler.MaxLOD = 0; + sampler.TCXAddressControlMode = TCM_CLAMP; + sampler.TCYAddressControlMode = TCM_CLAMP; + sampler.TCZAddressControlMode = TCM_CLAMP; + sampler.MaximumAnisotropy = RATIO21; + sampler.RAddressMinFilterRoundingEnable = true; + sampler.RAddressMagFilterRoundingEnable = true; + sampler.VAddressMinFilterRoundingEnable = true; + sampler.VAddressMagFilterRoundingEnable = true; + sampler.UAddressMinFilterRoundingEnable = true; + sampler.UAddressMagFilterRoundingEnable = true; + sampler.NonnormalizedCoordinateEnable = true; + } +} + #endif /* BLORP_GENX_EXEC_BRW_H */ diff --git a/src/intel/vulkan/genX_blorp_exec.c b/src/intel/vulkan/genX_blorp_exec.c index ff4b6c5ae16..29e72719220 100644 --- a/src/intel/vulkan/genX_blorp_exec.c +++ b/src/intel/vulkan/genX_blorp_exec.c @@ -116,6 +116,13 @@ blorp_get_surface_base_address(struct blorp_batch *batch) } #endif +static uint32_t +blorp_get_dynamic_state(struct blorp_batch *batch, + enum blorp_dynamic_state name) +{ + unreachable("Not implemented"); +} + static void * blorp_alloc_dynamic_state(struct blorp_batch *batch, uint32_t size,