spirv, nir: Add support for VK_EXT_mesh_shader
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