spirv: Treat EmitMeshTasksEXT as a terminating instruction.

glslang had a bug and didn't actually emit it as a terminating
instruction, therefore this went unnoticed thus far.  See
https://github.com/KhronosGroup/glslang/issues/3020.

Modified by Caio Oliveira to emit the corresponding NIR intrinsic
right before the halt.

Fixes: 7d1bcf1f55 ("spirv, nir: Handle EmitMeshTasksEXT opcode.")
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Reviewed-by: Jason Ekstrand <jason.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18442>
This commit is contained in:
Timur Kristóf
2022-09-06 16:12:02 +02:00
committed by Marge Bot
parent b9919b9980
commit 89f1727654
3 changed files with 37 additions and 23 deletions
-23
View File
@@ -6298,29 +6298,6 @@ vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode,
&b->nb, vtn_get_nir_ssa(b, w[1]), vtn_get_nir_ssa(b, w[2]));
break;
case SpvOpEmitMeshTasksEXT: {
/* Launches mesh shader workgroups from the task shader.
* Arguments are: vec(x, y, z), payload pointer
*/
nir_ssa_def *dimensions =
nir_vec3(&b->nb, vtn_get_nir_ssa(b, w[1]),
vtn_get_nir_ssa(b, w[2]),
vtn_get_nir_ssa(b, w[3]));
/* The payload variable is optional.
* We don't have a NULL deref in NIR, so just emit the explicit
* intrinsic when there is no payload.
*/
if (count == 4)
nir_launch_mesh_workgroups(&b->nb, dimensions);
else if (count == 5)
nir_launch_mesh_workgroups_with_payload_deref(&b->nb, dimensions,
vtn_get_nir_ssa(b, w[4]));
else
vtn_fail("Invalid EmitMeshTasksEXT.");
break;
}
default:
vtn_fail_with_opcode("Unhandled opcode", opcode);
}
+36
View File
@@ -304,6 +304,7 @@ vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode,
case SpvOpTerminateInvocation:
case SpvOpIgnoreIntersectionKHR:
case SpvOpTerminateRayKHR:
case SpvOpEmitMeshTasksEXT:
case SpvOpReturn:
case SpvOpReturnValue:
case SpvOpUnreachable:
@@ -750,6 +751,10 @@ vtn_process_block(struct vtn_builder *b,
block->branch_type = vtn_branch_type_terminate_ray;
return NULL;
case SpvOpEmitMeshTasksEXT:
block->branch_type = vtn_branch_type_emit_mesh_tasks;
return NULL;
case SpvOpBranchConditional: {
struct vtn_value *cond_val = vtn_untyped_value(b, block->branch[1]);
vtn_fail_if(!cond_val->type ||
@@ -1015,6 +1020,37 @@ vtn_emit_branch(struct vtn_builder *b, enum vtn_branch_type branch_type,
nir_terminate_ray(&b->nb);
nir_jump(&b->nb, nir_jump_halt);
break;
case vtn_branch_type_emit_mesh_tasks: {
assert(block);
assert(block->branch);
const uint32_t *w = block->branch;
vtn_assert((w[0] & SpvOpCodeMask) == SpvOpEmitMeshTasksEXT);
/* Launches mesh shader workgroups from the task shader.
* Arguments are: vec(x, y, z), payload pointer
*/
nir_ssa_def *dimensions =
nir_vec3(&b->nb, vtn_get_nir_ssa(b, w[1]),
vtn_get_nir_ssa(b, w[2]),
vtn_get_nir_ssa(b, w[3]));
/* The payload variable is optional.
* We don't have a NULL deref in NIR, so just emit the explicit
* intrinsic when there is no payload.
*/
const unsigned count = w[0] >> SpvWordCountShift;
if (count == 4)
nir_launch_mesh_workgroups(&b->nb, dimensions);
else if (count == 5)
nir_launch_mesh_workgroups_with_payload_deref(&b->nb, dimensions,
vtn_get_nir_ssa(b, w[4]));
else
vtn_fail("Invalid EmitMeshTasksEXT.");
nir_jump(&b->nb, nir_jump_halt);
break;
}
default:
vtn_fail("Invalid branch type");
}
+1
View File
@@ -142,6 +142,7 @@ enum vtn_branch_type {
vtn_branch_type_terminate_invocation,
vtn_branch_type_ignore_intersection,
vtn_branch_type_terminate_ray,
vtn_branch_type_emit_mesh_tasks,
vtn_branch_type_return,
};