From a268412533bc94af1cd0adcdc39e096f4d429316 Mon Sep 17 00:00:00 2001 From: Olivia Lee Date: Wed, 4 Jun 2025 00:49:53 -0700 Subject: [PATCH] panvk: allow sysvals to be dynamically-indexed We already do this for push constants, just extend the existing implementation. We need to update the push_consts sysval inside the cmd_prepare_push_uniforms loop now because indirect draws patch the sysvals. Previously this value was only used to read push constant FAUs, so we didn't care. Signed-off-by: Olivia Lee Reviewed-by: Boris Brezillon Acked-by: Erik Faye-Lund Reviewed-by: Lars-Ivar Hesselberg Simonsen Part-of: --- src/panfrost/vulkan/panvk_shader.h | 22 +++++++++---------- .../vulkan/panvk_vX_cmd_push_constant.c | 15 ++++++------- src/panfrost/vulkan/panvk_vX_shader.c | 22 ++++++++----------- 3 files changed, 27 insertions(+), 32 deletions(-) diff --git a/src/panfrost/vulkan/panvk_shader.h b/src/panfrost/vulkan/panvk_shader.h index 35e30da128b..108804e5a8b 100644 --- a/src/panfrost/vulkan/panvk_shader.h +++ b/src/panfrost/vulkan/panvk_shader.h @@ -104,7 +104,8 @@ struct panvk_graphics_sysvals { uint32_t noperspective_varyings; } vs; - aligned_u64 push_consts; + /* Address of sysval/push constant buffer used for indirect loads */ + aligned_u64 push_uniforms; aligned_u64 printf_buffer_address; struct panvk_input_attachment_info iam[INPUT_ATTACHMENT_MAP_SIZE]; @@ -123,9 +124,9 @@ struct panvk_graphics_sysvals { static_assert((sizeof(struct panvk_graphics_sysvals) % FAU_WORD_SIZE) == 0, "struct panvk_graphics_sysvals must be 8-byte aligned"); -static_assert((offsetof(struct panvk_graphics_sysvals, push_consts) % +static_assert((offsetof(struct panvk_graphics_sysvals, push_uniforms) % FAU_WORD_SIZE) == 0, - "panvk_graphics_sysvals::push_consts must be 8-byte aligned"); + "panvk_graphics_sysvals::push_uniforms must be 8-byte aligned"); #if PAN_ARCH <= 7 static_assert((offsetof(struct panvk_graphics_sysvals, desc) % FAU_WORD_SIZE) == 0, @@ -143,7 +144,8 @@ struct panvk_compute_sysvals { uint32_t x, y, z; } local_group_size; - aligned_u64 push_consts; + /* Address of sysval/push constant buffer used for indirect loads */ + aligned_u64 push_uniforms; aligned_u64 printf_buffer_address; #if PAN_ARCH <= 7 @@ -155,9 +157,9 @@ struct panvk_compute_sysvals { static_assert((sizeof(struct panvk_compute_sysvals) % FAU_WORD_SIZE) == 0, "struct panvk_compute_sysvals must be 8-byte aligned"); -static_assert((offsetof(struct panvk_compute_sysvals, push_consts) % +static_assert((offsetof(struct panvk_compute_sysvals, push_uniforms) % FAU_WORD_SIZE) == 0, - "panvk_compute_sysvals::push_consts must be 8-byte aligned"); + "panvk_compute_sysvals::push_uniforms must be 8-byte aligned"); #if PAN_ARCH <= 7 static_assert((offsetof(struct panvk_compute_sysvals, desc) % FAU_WORD_SIZE) == 0, @@ -241,11 +243,9 @@ static_assert((offsetof(struct panvk_compute_sysvals, desc) % FAU_WORD_SIZE) == #define load_sysval_entry(__b, __ptype, __bitsz, __name, __dyn_idx) \ nir_load_push_constant( \ __b, sysval_entry_size(__ptype, __name) / ((__bitsz) / 8), __bitsz, \ - nir_iadd_imm( \ - __b, \ - nir_imul_imm(__b, __dyn_idx, sysval_entry_size(__ptype, __name)), \ - sysval_offset(__ptype, __name)), \ - .base = SYSVALS_PUSH_CONST_BASE) + nir_imul_imm(__b, __dyn_idx, sysval_entry_size(__ptype, __name)), \ + .base = SYSVALS_PUSH_CONST_BASE + sysval_offset(__ptype, __name), \ + .range = sysval_size(__ptype, __name)) #if PAN_ARCH <= 7 enum panvk_bifrost_desc_table_type { diff --git a/src/panfrost/vulkan/panvk_vX_cmd_push_constant.c b/src/panfrost/vulkan/panvk_vX_cmd_push_constant.c index 067e4f2b384..91237a09169 100644 --- a/src/panfrost/vulkan/panvk_vX_cmd_push_constant.c +++ b/src/panfrost/vulkan/panvk_vX_cmd_push_constant.c @@ -47,14 +47,6 @@ panvk_per_arch(cmd_prepare_push_uniforms)(struct panvk_cmd_buffer *cmdbuf, if (!push_uniforms.gpu) return VK_ERROR_OUT_OF_DEVICE_MEMORY; - if (shader->vk.stage == MESA_SHADER_COMPUTE) { - cmdbuf->state.compute.sysvals.push_consts = - push_uniforms.gpu + (shader->fau.sysval_count * FAU_WORD_SIZE); - } else { - cmdbuf->state.gfx.sysvals.push_consts = - push_uniforms.gpu + (shader->fau.sysval_count * FAU_WORD_SIZE); - } - uint64_t *sysvals = shader->vk.stage == MESA_SHADER_COMPUTE ? (uint64_t *)&cmdbuf->state.compute.sysvals : (uint64_t *)&cmdbuf->state.gfx.sysvals; @@ -63,6 +55,13 @@ panvk_per_arch(cmd_prepare_push_uniforms)(struct panvk_cmd_buffer *cmdbuf, uint32_t w, fau = 0; for (uint32_t i = 0; i < repeat_count; i++) { + uint64_t addr = + push_uniforms.gpu + i * shader->fau.total_count * sizeof(uint64_t); + if (shader->vk.stage == MESA_SHADER_COMPUTE) + cmdbuf->state.compute.sysvals.push_uniforms = addr; + else + cmdbuf->state.gfx.sysvals.push_uniforms = addr; + /* After packing, the sysvals come first, followed by the user push * constants. The ordering is encoded shader side, so don't re-order * these loops. */ diff --git a/src/panfrost/vulkan/panvk_vX_shader.c b/src/panfrost/vulkan/panvk_vX_shader.c index f69482a1105..bafd3675930 100644 --- a/src/panfrost/vulkan/panvk_vX_shader.c +++ b/src/panfrost/vulkan/panvk_vX_shader.c @@ -571,9 +571,6 @@ collect_push_constant(struct nir_builder *b, nir_intrinsic_instr *intr, bool is_sysval = base >= SYSVALS_PUSH_CONST_BASE; uint32_t offset, size; - /* Sysvals should have a constant offset. */ - assert(!is_sysval || nir_src_is_const(intr->src[0])); - if (is_sysval) base -= SYSVALS_PUSH_CONST_BASE; @@ -583,11 +580,12 @@ collect_push_constant(struct nir_builder *b, nir_intrinsic_instr *intr, offset = base; size = nir_intrinsic_range(intr); - /* Flag the push_consts sysval as needed if we have an indirect offset. */ + /* Flag the push_uniforms sysval as needed if we have an indirect offset. + */ if (b->shader->info.stage == MESA_SHADER_COMPUTE) - shader_use_sysval(shader, compute, push_consts); + shader_use_sysval(shader, compute, push_uniforms); else - shader_use_sysval(shader, graphics, push_consts); + shader_use_sysval(shader, graphics, push_uniforms); } else { offset = base + nir_src_as_uint(intr->src[0]); size = (intr->def.bit_size / 8) * intr->def.num_components; @@ -614,9 +612,6 @@ move_push_constant(struct nir_builder *b, nir_intrinsic_instr *intr, void *data) if (is_sysval) base -= SYSVALS_PUSH_CONST_BASE; - /* Sysvals should have a constant offset. */ - assert(!is_sysval || nir_src_is_const(intr->src[0])); - b->cursor = nir_before_instr(&intr->instr); if (nir_src_is_const(intr->src[0])) { @@ -642,12 +637,13 @@ move_push_constant(struct nir_builder *b, nir_intrinsic_instr *intr, void *data) * zero in this pass. */ unsigned push_const_buf_offset = shader_remapped_sysval_offset( shader, b->shader->info.stage == MESA_SHADER_COMPUTE - ? sysval_offset(compute, push_consts) - : sysval_offset(graphics, push_consts)); + ? sysval_offset(compute, push_uniforms) + : sysval_offset(graphics, push_uniforms)); nir_def *push_const_buf = nir_load_push_constant( b, 1, 64, nir_imm_int(b, push_const_buf_offset)); - unsigned push_const_offset = - shader_remapped_fau_offset(shader, push_consts, base); + unsigned push_const_offset = is_sysval ? + shader_remapped_sysval_offset(shader, base) : + shader_remapped_push_const_offset(shader, base); nir_def *offset = nir_iadd_imm(b, intr->src[0].ssa, push_const_offset); unsigned align = nir_combined_align(nir_intrinsic_align_mul(intr), nir_intrinsic_align_offset(intr));