tu: Allocate consts for driver params as early as possible

Indirect draw calls upload VS params themselves, if indirect draw call
has zero instances GPU seem to still try to upload consts, however
with zer instances it doesn't apply draw state. Without the draw state
the the HLSQ_VS_CNTL values is stale, so less constants may be specified
than draw call expects. It is found that if CP_DRAW_INDIRECT_MULTI_1_DST_OFF
is less than 0x3f - GPU is happy even if the constlen is less than that.

As a workaround we allocate driver params first and ensure that VS
constlen always has the minimum size which is enough to upload driver
params.

Fixes one of the GPU hangs in "Disney Epic Mickey: Rebrushed" on a750.

Signed-off-by: Danylo Piliaiev <dpiliaiev@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32140>
This commit is contained in:
Danylo Piliaiev
2024-11-07 18:15:38 +01:00
committed by Marge Bot
parent 3e5d4d50c5
commit 2875332df5
4 changed files with 39 additions and 6 deletions
+4
View File
@@ -5966,6 +5966,10 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler,
so->constlen = MAX2(so->constlen, 4);
}
if (ctx->so->type == MESA_SHADER_VERTEX && ctx->compiler->gen >= 6) {
so->constlen = MAX2(so->constlen, 8);
}
if (gl_shader_stage_is_compute(so->type)) {
so->cs.local_invocation_id =
ir3_find_sysval_regid(so, SYSTEM_VALUE_LOCAL_INVOCATION_ID);
+9 -6
View File
@@ -1242,12 +1242,12 @@ ir3_get_driver_param_info(const nir_shader *shader, nir_intrinsic_instr *intr,
param_info->offset = IR3_DP_CS(local_group_size_x);
break;
case nir_intrinsic_load_subgroup_size:
assert(shader->info.stage == MESA_SHADER_COMPUTE ||
shader->info.stage == MESA_SHADER_FRAGMENT);
if (shader->info.stage == MESA_SHADER_COMPUTE) {
param_info->offset = IR3_DP_CS(subgroup_size);
} else {
} else if (shader->info.stage == MESA_SHADER_FRAGMENT) {
param_info->offset = IR3_DP_FS(subgroup_size);
} else {
return false;
}
break;
case nir_intrinsic_load_subgroup_id_shift_ir3:
@@ -1476,9 +1476,12 @@ ir3_setup_const_state(nir_shader *nir, struct ir3_shader_variant *v,
assert((const_state->ubo_state.size % 16) == 0);
ir3_alloc_driver_params(&const_state->allocs,
&const_state->num_driver_params, compiler,
v->type);
/* IR3_CONST_ALLOC_DRIVER_PARAMS could have been allocated earlier. */
if (const_state->allocs.consts[IR3_CONST_ALLOC_DRIVER_PARAMS].size_vec4 == 0) {
ir3_alloc_driver_params(&const_state->allocs,
&const_state->num_driver_params, compiler,
v->type);
}
if (const_state->image_dims.count > 0) {
ir3_const_reserve_space(&const_state->allocs, IR3_CONST_ALLOC_IMAGE_DIMS,
+8
View File
@@ -1474,6 +1474,14 @@ tu6_init_static_regs(struct tu_device *dev, struct tu_cs *cs)
if (phys_dev->info->a6xx.has_early_preamble) {
tu_cs_emit_regs(cs, A6XX_SP_FS_CTRL_REG0());
}
/* Workaround for draw state with constlen not being applied for
* zero-instance draw calls. See IR3_CONST_ALLOC_DRIVER_PARAMS allocation
* for more info.
*/
tu_cs_emit_pkt4(
cs, CHIP == A6XX ? REG_A6XX_HLSQ_VS_CNTL : REG_A7XX_HLSQ_VS_CNTL, 1);
tu_cs_emit(cs, A6XX_HLSQ_VS_CNTL_CONSTLEN(8) | A6XX_HLSQ_VS_CNTL_ENABLED);
}
/* Set always-identical registers used specifically for GMEM */
+18
View File
@@ -836,6 +836,24 @@ tu_lower_io(nir_shader *shader, struct tu_device *dev,
bool dynamic_renderpass,
struct ir3_const_allocations *const_allocs)
{
/* Allocate driver params as early as possible as a workaround for the
* following case:
* - CP_DRAW_INDIRECT_MULTI_1_DST_OFF apparently tries to upload consts
* even when there are 0 instances.
* - With zero instances, the draw state for VS constlen is not applied.
* - constlen therefor uses stale value and if
* CP_DRAW_INDIRECT_MULTI_1_DST_OFF is higher than 0x3f - GPU hangs.
*
* To not rely on undefined behaviour, we will always allocate enough space
* to upload driver params.
*/
if (shader->info.stage == MESA_SHADER_VERTEX) {
uint32_t num_driver_params =
ir3_nir_scan_driver_consts(dev->compiler, shader, nullptr);
ir3_alloc_driver_params(const_allocs, &num_driver_params, dev->compiler,
shader->info.stage);
}
struct tu_const_state *const_state = &tu_shader->const_state;
const_state->push_consts = (struct tu_push_constant_range) {
.lo_dwords = 0,