diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index 09ce0a4c37f..4c4a7b7ba6f 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -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); diff --git a/src/freedreno/ir3/ir3_nir.c b/src/freedreno/ir3/ir3_nir.c index 5240e8e61a7..d0991fca1ad 100644 --- a/src/freedreno/ir3/ir3_nir.c +++ b/src/freedreno/ir3/ir3_nir.c @@ -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, diff --git a/src/freedreno/vulkan/tu_cmd_buffer.cc b/src/freedreno/vulkan/tu_cmd_buffer.cc index 0b114be1ec5..f46a9384f35 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.cc +++ b/src/freedreno/vulkan/tu_cmd_buffer.cc @@ -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 */ diff --git a/src/freedreno/vulkan/tu_shader.cc b/src/freedreno/vulkan/tu_shader.cc index ca7a6da65ca..6cae345c44e 100644 --- a/src/freedreno/vulkan/tu_shader.cc +++ b/src/freedreno/vulkan/tu_shader.cc @@ -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,