Skip to content

spirv, nir: Add support for VK_EXT_mesh_shader

Timur Kristóf requested to merge Venemo/mesa:vk_ext_mesh_nir_spirv into main

VK_EXT_mesh_shader support in SPIR-V and NIR

Add the necessary code to NIR and spirv_to_nir to support task and mesh shaders that use the newly released VK_EXT_mesh_shader extension. Note that the commits included in this MR have been already reviewed here.

For further info please refer to the Khronos blog.

Short summary:

  • Primitive indices are an "array of arrays" indexed by the primitive index (as opposed to a flat array in NV_mesh_shader)
  • Mesh shaders have to declare their output using the new SetMeshOutputsEXT opcode before writing any outputs
  • Task shaders have to use the new EmitMeshTasksEXT opcode to dispatch 3D mesh shader workgroups
  • A new CullPrimitiveEXT output is available so that app developers can easily cull primitives
  • A new TaskPayloadWorkgroupEXT storage class is added for task shader payload output

Comparison between NV_mesh_shader and EXT_mesh_shader

NV_mesh_shader EXT_mesh_shader
Dispatch dimensions 1 dimensional 3 dimensional
Dispatch offset taskCount Not supported
Dispatch indirect buffer format (taskCount, firstTask) (x, y, z)
Mesh shader: primitive indices Flat array,
contains the indices or all primitives contiguously
Array of arrays,
addressed by primitive index (behaves similarly to a per-primitive output, but isn't counted among per-primitive outputs)
Mesh shader: output primitive count Primitive count output,
can be written at any point in the shader.
Argument of SetMeshOutputsEXT, value is taken from the first invocation.
Mesh shader: output vertex count The exact number is not known in the shader, it is up to the implementation to figure it out or allocate the max possible amount. Argument of SetMeshOutputsEXT, value is taken from the first invocation.
Mesh shader: output arrays Read/write at any point in the shader. Write-only, only after SetMeshOutputsEXT
Mesh shader: output memory limits Assumes that the implementation uses shared memory for the mesh shader outputs. Separate limits for outputs and shared memory.
Mesh shader: culling output primitives Not supported. CullPrimitiveEXT
boolean per-primitive output.
Mesh/Task shader: workgroup ID 1 dimensional,
includes firstTask
3 dimensional
Mesh/Task shader: number of workgroups Not supported 3 dimensional
Task shader: output types Payload (passed to Mesh shader),
Task count output
Payload (passed to Mesh shader)
Task shader: payload storage class Output TaskPayloadWorkgroupEXT dedicated storage class
Task shader: payload memory limits Assumes that the implementation uses shared memory for the payload. Separate limits for payload and shared memory.
Task shader: launched mesh shader workgroups 1 dimensional,
task count output, can be written at any point in the shader
3 dimensional,
arguments of EmitMeshTasksEXT, values are taken from the first invocation

New SPIR-V opcodes in EXT_mesh_shader

TaskPayloadWorkgroupEXT storage class

  • Only 1 variable with this storage class is allowed
  • At least up to 16K bytes
  • Expected to behave like shared memory
  • Passed from Task to Mesh shader
  • Read/write in Task shader
  • Read-only in Mesh shader

SetMeshOutputsEXT (Mesh shaders)

  • Specifies the final vertex and primitive counts of the current Mesh shader workgroup
  • Arguments: vertex and primitive count, max 256
  • Must occour before any writes to the output arrays
  • Must be in uniform control flow
  • The arguments can be divergent, then the value from the first invocation is used

EmitMeshTasksEXT (Task shaders)

  • Launches a Mesh shader dispatch along the specified dimensions
  • Arguments: x, y, z dimensions, and a pointer to the payload variable
  • Must be in uniform control flow
  • The arguments can be divergent, then the value from the first invocation is used
Edited by Timur Kristóf

Merge request reports