anv: rework tbimr push constant workaround

We'll want to know about the empty push constant for device generated
commands. It's easier if the information is stored in
anv_pipeline_bind_map::push_ranges[].

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: José Roberto de Souza <jose.souza@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32828>
This commit is contained in:
Lionel Landwerlin 2024-11-28 21:33:30 +02:00 committed by Marge Bot
parent 6281b207db
commit 1448778385
2 changed files with 29 additions and 39 deletions

View file

@ -175,6 +175,7 @@ anv_nir_compute_push_layout(nir_shader *nir,
}
}
unsigned n_push_ranges = 0;
if (push_ubo_ranges) {
brw_nir_analyze_ubo_ranges(compiler, nir, prog_data->ubo_ranges);
@ -188,10 +189,8 @@ anv_nir_compute_push_layout(nir_shader *nir,
}
assert(total_push_regs <= max_push_regs);
int n = 0;
if (push_constant_range.length > 0)
map->push_ranges[n++] = push_constant_range;
map->push_ranges[n_push_ranges++] = push_constant_range;
if (robust_flags & BRW_ROBUSTNESS_UBO) {
const uint32_t push_reg_mask_offset =
@ -208,7 +207,7 @@ anv_nir_compute_push_layout(nir_shader *nir,
if (ubo_range->length == 0)
continue;
if (n >= 4) {
if (n_push_ranges >= 4) {
memset(ubo_range, 0, sizeof(*ubo_range));
continue;
}
@ -217,7 +216,7 @@ anv_nir_compute_push_layout(nir_shader *nir,
const struct anv_pipeline_binding *binding =
&push_map->block_to_descriptor[ubo_range->block];
map->push_ranges[n++] = (struct anv_push_range) {
map->push_ranges[n_push_ranges++] = (struct anv_push_range) {
.set = binding->set,
.index = binding->index,
.dynamic_offset_index = binding->dynamic_offset_index,
@ -234,7 +233,7 @@ anv_nir_compute_push_layout(nir_shader *nir,
range_start_reg += ubo_range->length;
}
} else {
} else if (push_constant_range.length > 0) {
/* For Ivy Bridge, the push constants packets have a different
* rule that would require us to iterate in the other direction
* and possibly mess around with dynamic state base address.
@ -243,7 +242,26 @@ anv_nir_compute_push_layout(nir_shader *nir,
* In the compute case, we don't have multiple push ranges so it's
* better to just provide one in push_ranges[0].
*/
map->push_ranges[0] = push_constant_range;
map->push_ranges[n_push_ranges++] = push_constant_range;
}
/* Pass a single-register push constant payload for the PS stage even if
* empty, since PS invocations with zero push constant cycles have been
* found to cause hangs with TBIMR enabled. See HSDES #22020184996.
*
* XXX - Use workaround infrastructure and final workaround when provided
* by hardware team.
*/
if (n_push_ranges == 0 &&
nir->info.stage == MESA_SHADER_FRAGMENT &&
devinfo->needs_null_push_constant_tbimr_workaround) {
map->push_ranges[n_push_ranges++] = (struct anv_push_range) {
.set = ANV_DESCRIPTOR_SET_NULL,
.start = 0,
.length = 1,
};
assert(prog_data->nr_params == 0);
prog_data->nr_params = 32 / 4;
}
if (nir->info.stage == MESA_SHADER_FRAGMENT && fragment_dynamic) {

View file

@ -195,6 +195,9 @@ get_push_range_address(struct anv_cmd_buffer *cmd_buffer,
cmd_buffer, gfx_state->base.push_constants_state);
}
case ANV_DESCRIPTOR_SET_NULL:
return cmd_buffer->device->workaround_address;
default: {
assert(range->set < MAX_SETS);
struct anv_descriptor_set *set =
@ -258,6 +261,7 @@ get_push_range_bound_size(struct anv_cmd_buffer *cmd_buffer,
return gfx_state->base.pipeline->layout.set[
range->index].layout->descriptor_buffer_surface_size;
case ANV_DESCRIPTOR_SET_NULL:
case ANV_DESCRIPTOR_SET_PUSH_CONSTANTS:
return (range->start + range->length) * 32;
@ -373,32 +377,6 @@ cmd_buffer_emit_push_constant(struct anv_cmd_buffer *cmd_buffer,
}
#if GFX_VER >= 12
static void
emit_null_push_constant_tbimr_workaround(struct anv_cmd_buffer *cmd_buffer)
{
/* Pass a single-register push constant payload for the PS
* stage even if empty, since PS invocations with zero push
* constant cycles have been found to cause hangs with TBIMR
* enabled. See HSDES #22020184996.
*
* XXX - Use workaround infrastructure and final workaround
* when provided by hardware team.
*/
const struct anv_address null_addr = cmd_buffer->device->workaround_address;
uint32_t *dw = anv_batch_emitn(
&cmd_buffer->batch, 4,
GENX(3DSTATE_CONSTANT_ALL),
.ShaderUpdateEnable = (1 << MESA_SHADER_FRAGMENT),
.PointerBufferMask = 1,
.MOCS = isl_mocs(&cmd_buffer->device->isl_dev, 0, false));
GENX(3DSTATE_CONSTANT_ALL_DATA_pack)(
&cmd_buffer->batch, dw + 2,
&(struct GENX(3DSTATE_CONSTANT_ALL_DATA)) {
.PointerToConstantBuffer = null_addr,
.ConstantBufferReadLength = 1,
});
}
static void
cmd_buffer_emit_push_constant_all(struct anv_cmd_buffer *cmd_buffer,
uint32_t shader_mask,
@ -406,12 +384,6 @@ cmd_buffer_emit_push_constant_all(struct anv_cmd_buffer *cmd_buffer,
uint32_t buffer_count)
{
if (buffer_count == 0) {
if (cmd_buffer->device->info->needs_null_push_constant_tbimr_workaround &&
(shader_mask & (1 << MESA_SHADER_FRAGMENT))) {
emit_null_push_constant_tbimr_workaround(cmd_buffer);
shader_mask &= ~(1 << MESA_SHADER_FRAGMENT);
}
if (shader_mask) {
anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_CONSTANT_ALL), c) {
c.ShaderUpdateEnable = shader_mask;