nvk: Prepare cbuf for mesh shader support

Signed-off-by: Mary Guillemard <mary@mary.zone>
Reviewed-by: Mel Henning <mhenning@darkrefraction.com>
Tested-by: Thomas H.P. Andersen <phomes@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27196>
This commit is contained in:
Mary Guillemard 2026-02-05 09:21:49 +01:00 committed by Marge Bot
parent 3348003735
commit 3286990481
4 changed files with 59 additions and 9 deletions

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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) {

View file

@ -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