diff --git a/src/panfrost/vulkan/panvk_shader.h b/src/panfrost/vulkan/panvk_shader.h index f7aa8ff1642..cde8389aa1e 100644 --- a/src/panfrost/vulkan/panvk_shader.h +++ b/src/panfrost/vulkan/panvk_shader.h @@ -20,6 +20,8 @@ #include "panvk_macros.h" #include "panvk_pipeline_layout.h" +#define MAX_VS_ATTRIBS 16 + struct nir_shader; struct pan_blend_state; struct panvk_device; diff --git a/src/panfrost/vulkan/panvk_vX_cmd_buffer.c b/src/panfrost/vulkan/panvk_vX_cmd_buffer.c index fca0c2d23ca..e2886dfd4cf 100644 --- a/src/panfrost/vulkan/panvk_vX_cmd_buffer.c +++ b/src/panfrost/vulkan/panvk_vX_cmd_buffer.c @@ -924,18 +924,13 @@ panvk_draw_prepare_vs_attribs(struct panvk_cmd_buffer *cmdbuf, pipeline->base.img_access_mask & BITFIELD_BIT(MESA_SHADER_VERTEX) ? pipeline->base.layout->num_imgs : 0; - unsigned attrib_count = pipeline->state.vs.attribs.attrib_count + num_imgs; + unsigned num_vs_attribs = pipeline->state.vs.attribs.attrib_count; + unsigned attrib_count = + num_imgs ? MAX_VS_ATTRIBS + num_imgs : num_vs_attribs; if (cmdbuf->state.gfx.vs.attribs || !attrib_count) return; - if (!pipeline->state.vs.attribs.buf_count) { - panvk_prepare_img_attribs(cmdbuf, desc_state, &pipeline->base); - cmdbuf->state.gfx.vs.attrib_bufs = desc_state->img.attrib_bufs; - cmdbuf->state.gfx.vs.attribs = desc_state->img.attribs; - return; - } - unsigned attrib_buf_count = pipeline->state.vs.attribs.buf_count * 2; struct panfrost_ptr bufs = pan_pool_alloc_desc_array( &cmdbuf->desc_pool.base, attrib_buf_count + 1, ATTRIBUTE_BUFFER); @@ -950,7 +945,7 @@ panvk_draw_prepare_vs_attribs(struct panvk_cmd_buffer *cmdbuf, &attrib_buf_descs[i * 2]); } - for (unsigned i = 0; i < pipeline->state.vs.attribs.attrib_count; i++) { + for (unsigned i = 0; i < num_vs_attribs; i++) { unsigned buf_idx = pipeline->state.vs.attribs.attrib[i].buf; panvk_draw_emit_attrib(draw, &pipeline->state.vs.attribs.attrib[i], @@ -960,11 +955,17 @@ panvk_draw_prepare_vs_attribs(struct panvk_cmd_buffer *cmdbuf, } if (num_imgs) { + /* Image load/store are passed a fixed offset, so we can make vertex input + * dynamic. Images are always placed after all potential vertex + * attributes. Buffers are tightly packed since they don't interfere with + * the vertex shader. + */ unsigned bufs_offset = pipeline->state.vs.attribs.buf_count * pan_size(ATTRIBUTE_BUFFER) * 2; - unsigned attribs_offset = - pipeline->state.vs.attribs.buf_count * pan_size(ATTRIBUTE); + unsigned attribs_offset = MAX_VS_ATTRIBS * pan_size(ATTRIBUTE); + memset(attribs.cpu + num_vs_attribs * pan_size(ATTRIBUTE), 0, + (MAX_VS_ATTRIBS - num_vs_attribs) * pan_size(ATTRIBUTE)); panvk_fill_img_attribs(cmdbuf, desc_state, &pipeline->base, bufs.cpu + bufs_offset, attribs.cpu + attribs_offset, diff --git a/src/panfrost/vulkan/panvk_vX_shader.c b/src/panfrost/vulkan/panvk_vX_shader.c index 1388ed2355f..01b75698d6a 100644 --- a/src/panfrost/vulkan/panvk_vX_shader.c +++ b/src/panfrost/vulkan/panvk_vX_shader.c @@ -361,8 +361,7 @@ panvk_per_arch(shader_create)(struct panvk_device *dev, gl_shader_stage stage, } if (stage == MESA_SHADER_VERTEX) - NIR_PASS_V(nir, pan_lower_image_index, - util_bitcount64(nir->info.inputs_read)); + NIR_PASS_V(nir, pan_lower_image_index, MAX_VS_ATTRIBS); struct sysval_options sysval_options = { .static_blend_constants = @@ -389,8 +388,13 @@ panvk_per_arch(shader_create)(struct panvk_device *dev, gl_shader_stage stage, panvk_per_arch(pipeline_layout_total_ubo_count)(layout); shader->info.sampler_count = layout->num_samplers; shader->info.texture_count = layout->num_textures; + + /* Image attributes start at MAX_VS_ATTRIBS in the VS attribute table, + * and zero in other stages. + */ if (shader->has_img_access) - shader->info.attribute_count += layout->num_imgs; + shader->info.attribute_count = + layout->num_imgs + (stage == MESA_SHADER_VERTEX ? MAX_VS_ATTRIBS : 0); shader->local_size.x = nir->info.workgroup_size[0]; shader->local_size.y = nir->info.workgroup_size[1];