diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index f9b93debd55..cf507cc86e3 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -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); } diff --git a/src/compiler/spirv/vtn_cfg.c b/src/compiler/spirv/vtn_cfg.c index 9215bc86dae..140728cd57b 100644 --- a/src/compiler/spirv/vtn_cfg.c +++ b/src/compiler/spirv/vtn_cfg.c @@ -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"); } diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index b4b0513ee07..eaf8219b093 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -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, };