From 3286990481056591140ce4bcd01c85dfe339dee5 Mon Sep 17 00:00:00 2001 From: Mary Guillemard Date: Thu, 5 Feb 2026 09:21:49 +0100 Subject: [PATCH] nvk: Prepare cbuf for mesh shader support Signed-off-by: Mary Guillemard Reviewed-by: Mel Henning Tested-by: Thomas H.P. Andersen Part-of: --- src/nouveau/vulkan/nvk_cmd_buffer.c | 9 ++++++-- src/nouveau/vulkan/nvk_cmd_draw.c | 35 ++++++++++++++++++++++++++--- src/nouveau/vulkan/nvk_shader.c | 13 +++++++++-- src/nouveau/vulkan/nvk_shader.h | 11 +++++++-- 4 files changed, 59 insertions(+), 9 deletions(-) diff --git a/src/nouveau/vulkan/nvk_cmd_buffer.c b/src/nouveau/vulkan/nvk_cmd_buffer.c index 85540b8caa5..c28d1168f57 100644 --- a/src/nouveau/vulkan/nvk_cmd_buffer.c +++ b/src/nouveau/vulkan/nvk_cmd_buffer.c @@ -873,7 +873,7 @@ nvk_cmd_bind_shaders(struct vk_command_buffer *vk_cmd, } } -#define NVK_VK_GRAPHICS_STAGE_BITS VK_SHADER_STAGE_ALL_GRAPHICS +#define NVK_VK_GRAPHICS_STAGE_BITS (VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_TASK_BIT_EXT | VK_SHADER_STAGE_MESH_BIT_EXT) void nvk_cmd_dirty_cbufs_for_descriptors(struct nvk_cmd_buffer *cmd, @@ -883,10 +883,15 @@ nvk_cmd_dirty_cbufs_for_descriptors(struct nvk_cmd_buffer *cmd, if (!(stages & NVK_VK_GRAPHICS_STAGE_BITS)) return; + const struct nvk_shader *mesh_shader = + cmd->state.gfx.shaders[MESA_SHADER_MESH]; + const bool has_task_shader = + mesh_shader != NULL && mesh_shader->info.mesh.has_task_shader; + uint32_t groups = 0; u_foreach_bit(i, stages & NVK_VK_GRAPHICS_STAGE_BITS) { mesa_shader_stage stage = vk_to_mesa_shader_stage(1 << i); - uint32_t g = nvk_cbuf_binding_for_stage(stage); + uint32_t g = nvk_cbuf_binding_for_stage(stage, has_task_shader); groups |= BITFIELD_BIT(g); } diff --git a/src/nouveau/vulkan/nvk_cmd_draw.c b/src/nouveau/vulkan/nvk_cmd_draw.c index 19ca89acbe6..fca0bbae671 100644 --- a/src/nouveau/vulkan/nvk_cmd_draw.c +++ b/src/nouveau/vulkan/nvk_cmd_draw.c @@ -2219,6 +2219,11 @@ nvk_cmd_flush_gfx_shaders(struct nvk_cmd_buffer *cmd) struct nvk_shader *type_shader[6] = { NULL, }; uint32_t types_dirty = 0; + const struct nvk_shader *mesh_shader = + cmd->state.gfx.shaders[MESA_SHADER_MESH]; + const bool has_task_shader = + mesh_shader != NULL && mesh_shader->info.mesh.has_task_shader; + u_foreach_bit(s, cmd->state.gfx.shaders_dirty & NVK_SHADER_STAGE_GRAPHICS_BITS) { mesa_shader_stage stage = vk_to_mesa_shader_stage(1 << s); @@ -2234,9 +2239,14 @@ nvk_cmd_flush_gfx_shaders(struct nvk_cmd_buffer *cmd) assert(type_shader[type] == NULL); type_shader[type] = shader; + /* In case of passthrough GS with mesh, we already handled binding of the geometry stage */ + if (stage == MESA_SHADER_MESH && shader->info.mesh.has_gs_sph) + types_dirty &= ~BITFIELD_BIT(NV9097_SET_PIPELINE_SHADER_TYPE_GEOMETRY); + const struct nvk_cbuf_map *cbuf_map = &shader->cbuf_map; struct nvk_cbuf_group *cbuf_group = - &cmd->state.gfx.cbuf_groups[nvk_cbuf_binding_for_stage(stage)]; + &cmd->state.gfx.cbuf_groups[nvk_cbuf_binding_for_stage( + stage, has_task_shader)]; for (uint32_t i = 0; i < cbuf_map->cbuf_count; i++) { if (memcmp(&cbuf_group->cbufs[i], &cbuf_map->cbufs[i], sizeof(cbuf_group->cbufs[i])) != 0) { @@ -2245,6 +2255,20 @@ nvk_cmd_flush_gfx_shaders(struct nvk_cmd_buffer *cmd) } } } + + if (stage == MESA_SHADER_MESH) { + /* If we change the mesh stage, this could also affect the tesselation + * stage */ + types_dirty |= + BITFIELD_BIT(NV9097_SET_PIPELINE_SHADER_TYPE_TESSELLATION); + + /* If we unbind the mesh stage, this could also affect the geometry + * stage (for per primitive passthrough header) */ + if (shader == NULL) + types_dirty |= + BITFIELD_BIT(NV9097_SET_PIPELINE_SHADER_TYPE_GEOMETRY); + } + } u_foreach_bit(type, types_dirty) { @@ -4204,14 +4228,19 @@ nvk_cmd_flush_gfx_cbufs(struct nvk_cmd_buffer *cmd) const uint32_t min_cbuf_alignment = nvk_min_cbuf_alignment(&pdev->info); struct nvk_descriptor_state *desc = &cmd->state.gfx.descriptors; + const struct nvk_shader *mesh_shader = + cmd->state.gfx.shaders[MESA_SHADER_MESH]; + const bool has_task_shader = + mesh_shader != NULL && mesh_shader->info.mesh.has_task_shader; + /* Find cbuf maps for the 5 cbuf groups */ const struct nvk_shader *cbuf_shaders[5] = { NULL, }; - for (mesa_shader_stage stage = 0; stage < MESA_SHADER_STAGES; stage++) { + for (mesa_shader_stage stage = 0; stage < MESA_SHADER_MESH_STAGES; stage++) { const struct nvk_shader *shader = cmd->state.gfx.shaders[stage]; if (shader == NULL) continue; - uint32_t group = nvk_cbuf_binding_for_stage(stage); + uint32_t group = nvk_cbuf_binding_for_stage(stage, has_task_shader); assert(group < ARRAY_SIZE(cbuf_shaders)); cbuf_shaders[group] = shader; } diff --git a/src/nouveau/vulkan/nvk_shader.c b/src/nouveau/vulkan/nvk_shader.c index 4b95e3f3d78..0aff769d729 100644 --- a/src/nouveau/vulkan/nvk_shader.c +++ b/src/nouveau/vulkan/nvk_shader.c @@ -700,8 +700,15 @@ mesa_to_nv9097_shader_type(mesa_shader_stage stage) } uint32_t -nvk_pipeline_bind_group(mesa_shader_stage stage) +nvk_pipeline_bind_group(mesa_shader_stage stage, bool has_task_shader) { + if (stage == MESA_SHADER_MESH && !has_task_shader) + return MESA_SHADER_VERTEX; + else if (stage == MESA_SHADER_MESH) + return MESA_SHADER_TESS_EVAL; + else if (stage == MESA_SHADER_TASK) + return MESA_SHADER_VERTEX; + return stage; } @@ -741,6 +748,8 @@ nvk_shader_fill_push(struct nvk_device *dev, nv_push_init(&push, push_dw, ARRAY_SIZE(push_dw), nvk_queue_subchannels_from_engines(NVKMD_ENGINE_3D)); + bool has_task_shader = shader->info.stage == MESA_SHADER_MESH && + shader->info.mesh.has_task_shader; const uint32_t type = mesa_to_nv9097_shader_type(shader->info.stage); /* We always map index == type */ @@ -778,7 +787,7 @@ nvk_shader_fill_push(struct nvk_device *dev, P_MTHD(p, NVC397, SET_PIPELINE_REGISTER_COUNT(idx)); P_NVC397_SET_PIPELINE_REGISTER_COUNT(p, idx, shader->info.num_gprs); P_NVC397_SET_PIPELINE_BINDING(p, idx, - nvk_pipeline_bind_group(shader->info.stage)); + nvk_pipeline_bind_group(shader->info.stage, has_task_shader)); if (shader->info.stage == MESA_SHADER_TESS_CTRL || shader->info.stage == MESA_SHADER_TESS_EVAL) { diff --git a/src/nouveau/vulkan/nvk_shader.h b/src/nouveau/vulkan/nvk_shader.h index f5d1fcbfe24..82de2bd2cff 100644 --- a/src/nouveau/vulkan/nvk_shader.h +++ b/src/nouveau/vulkan/nvk_shader.h @@ -48,8 +48,15 @@ nvk_last_vtgm_shader_stage(VkShaderStageFlags stages) } static inline uint32_t -nvk_cbuf_binding_for_stage(mesa_shader_stage stage) +nvk_cbuf_binding_for_stage(mesa_shader_stage stage, bool has_task_shader) { + if (stage == MESA_SHADER_MESH && !has_task_shader) + return MESA_SHADER_VERTEX; + else if (stage == MESA_SHADER_MESH) + return MESA_SHADER_TESS_EVAL; + else if (stage == MESA_SHADER_TASK) + return MESA_SHADER_VERTEX; + return stage; } @@ -155,6 +162,6 @@ nvk_compile_nir_shader(struct nvk_device *dev, nir_shader *nir, struct nvk_shader **shader_out); uint32_t mesa_to_nv9097_shader_type(mesa_shader_stage stage); -uint32_t nvk_pipeline_bind_group(mesa_shader_stage stage); +uint32_t nvk_pipeline_bind_group(mesa_shader_stage stage, bool has_task_shader); #endif