Skip to content

OutputTrianglesEXT Execution Mode not found (Mesh Shader) #373

@jre0

Description

@jre0

I'm trying to make a mesh shader but some validation stage appears to incorrectly kick back with [OutputTrianglesEXT Execution Mode](error: [VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07054] The PrimitiveTriangleIndicesEXT decoration must be used with the OutputTrianglesEXT Execution Mode.) I do include OutputTrianglesEXT so this error appears to be a mistake.
Is it still possible to use the installed spirv tools instead of the rust crate? If so, the documentation appears out of date because I tried to use cargo run --features use-installed-tools and it says command not found. If I can use the installed tools, I might be able to avoid this error. I appreciate any help, including hints on where to start if I have to fix the bug myself.

Expected Behaviour

Because I use output_triangles_ext, I expect primitive_triangle_indices_ext to be available.

Example & Steps To Reproduce

Here is the shader code. It compiles because I commented out the lines that set the vertex indices. If you add them, it produces the error about requiring OutputTrianglesEXT. I used spirv tools spirv-dis to inspect the output and OutputTrianglesEXT is there.

#![no_std]
#![allow(unexpected_cfgs)]

use glam::*;
use spirv_std::arch::{emit_mesh_tasks_ext, set_mesh_outputs_ext};
use spirv_std::spirv;

#[spirv(mesh_ext(
    threads(1),
    output_vertices = 3,
    output_primitives_ext = 1,
    output_triangles_ext,
))]
pub fn mesh(
    #[spirv(position)] positions: &mut [Vec4; 3],
    // #[spirv(primitive_triangle_indices_ext)] indices: &mut [UVec3; 1],
) {
    unsafe {
        set_mesh_outputs_ext(3, 1);
    }
    positions[0] = Vec4::default();
    positions[1] = Vec4::default();
    // indices[0] = UVec3::new(0, 1, 2);
}

System Info

  • Rust: rustc 1.89.0-nightly (be19eda0d 2025-06-22)
  • OS: Kubuntu 24.04, kernel 6.8.0-79-generic (64-bit)
  • GPU: NVIDIA GeForce GTX 1660 Ti/PCIe/SSE2
  • SPIR-V: SPIRV-Tools v2025.3 v2025.3.rc1-0-g33e02568

Spirv and Backtrace

Spirv dis

; SPIR-V
; Version: 1.6
; Generator: Google rspirv; 0
; Bound: 190
; Schema: 0
               OpCapability Shader
               OpCapability MeshShadingEXT
               OpCapability VulkanMemoryModel
               OpExtension "SPV_EXT_mesh_shader"
               OpMemoryModel Logical Vulkan
               OpEntryPoint TaskEXT %1 "task"
               OpEntryPoint MeshEXT %2 "mesh" %3 %4 %5 %gl_Position
               OpEntryPoint Fragment %7 "fragment" %8
               OpExecutionMode %1 LocalSize 1 1 1
               OpExecutionMode %2 LocalSize 1 1 1
               OpExecutionMode %2 OutputVertices 3
               OpExecutionMode %2 OutputPrimitivesEXT 1
               OpExecutionMode %2 OutputTrianglesEXT
               OpExecutionMode %7 OriginUpperLeft
               OpMemberDecorate %_struct_16 0 Offset 0
               OpMemberDecorate %_struct_16 1 Offset 16
               OpMemberDecorate %_struct_16 2 Offset 32
               OpMemberDecorate %_struct_16 3 Offset 48
               OpMemberDecorate %_struct_17 0 Offset 0
               OpMemberDecorate %_struct_17 1 Offset 64
               OpDecorate %_struct_19 Block
               OpMemberDecorate %_struct_19 0 Offset 0
               OpDecorate %_runtimearr_v2float ArrayStride 8
               OpDecorate %_struct_21 Block
               OpMemberDecorate %_struct_21 0 Offset 0
               OpDecorate %_arr_v4float_uint_3 ArrayStride 16
               OpDecorate %3 Binding 0
               OpDecorate %3 DescriptorSet 0
               OpDecorate %4 NonWritable
               OpDecorate %4 Binding 1
               OpDecorate %4 DescriptorSet 0
               OpDecorate %5 NonWritable
               OpDecorate %5 Binding 2
               OpDecorate %5 DescriptorSet 0
               OpDecorate %gl_Position BuiltIn Position
               OpDecorate %8 Location 0
       %void = OpTypeVoid
         %24 = OpTypeFunction %void
       %uint = OpTypeInt 32 0
     %uint_1 = OpConstant %uint 1
      %float = OpTypeFloat 32
    %v4float = OpTypeVector %float 4
 %_struct_16 = OpTypeStruct %v4float %v4float %v4float %v4float
 %_struct_17 = OpTypeStruct %_struct_16 %_struct_16
 %_struct_19 = OpTypeStruct %_struct_17
%_ptr_Uniform__struct_19 = OpTypePointer Uniform %_struct_19
    %v2float = OpTypeVector %float 2
%_runtimearr_v2float = OpTypeRuntimeArray %v2float
 %_struct_21 = OpTypeStruct %_runtimearr_v2float
%_ptr_StorageBuffer__struct_21 = OpTypePointer StorageBuffer %_struct_21
     %uint_3 = OpConstant %uint 3
%_arr_v4float_uint_3 = OpTypeArray %v4float %uint_3
%_ptr_Output__arr_v4float_uint_3 = OpTypePointer Output %_arr_v4float_uint_3
          %3 = OpVariable %_ptr_Uniform__struct_19 Uniform
     %uint_0 = OpConstant %uint 0
          %4 = OpVariable %_ptr_StorageBuffer__struct_21 StorageBuffer
          %5 = OpVariable %_ptr_StorageBuffer__struct_21 StorageBuffer
%_ptr_Uniform__struct_16 = OpTypePointer Uniform %_struct_16
       %bool = OpTypeBool
%_ptr_StorageBuffer_v2float = OpTypePointer StorageBuffer %v2float
    %float_1 = OpConstant %float 1
         %41 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
%_ptr_Output_v4float = OpTypePointer Output %v4float
%gl_Position = OpVariable %_ptr_Output__arr_v4float_uint_3 Output
          %8 = OpVariable %_ptr_Output_v4float Output
          %1 = OpFunction %void None %24
         %43 = OpLabel
               OpEmitMeshTasksEXT %uint_1 %uint_1 %uint_1
               OpFunctionEnd
          %2 = OpFunction %void None %24
         %46 = OpLabel
               OpSelectionMerge %188 None
               OpSwitch %uint_0 %189
        %189 = OpLabel
         %49 = OpArrayLength %uint %4 0
         %51 = OpArrayLength %uint %5 0
               OpSetMeshOutputsEXT %uint_3 %uint_1
         %52 = OpInBoundsAccessChain %_ptr_Uniform__struct_16 %3 %uint_0 %uint_0
         %53 = OpLoad %_struct_16 %52
         %54 = OpULessThan %bool %uint_0 %49
               OpSelectionMerge %56 None
               OpBranchConditional %54 %56 %57
         %56 = OpLabel
         %58 = OpInBoundsAccessChain %_ptr_StorageBuffer_v2float %4 %uint_0 %uint_0
         %59 = OpLoad %v2float %58
         %60 = OpCompositeExtract %float %59 0
         %61 = OpCompositeExtract %float %59 1
         %64 = OpCompositeExtract %v4float %53 0
         %65 = OpCompositeExtract %float %64 0
         %66 = OpFMul %float %65 %60
         %67 = OpCompositeExtract %float %64 1
         %68 = OpFMul %float %67 %60
         %69 = OpCompositeExtract %float %64 2
         %70 = OpFMul %float %69 %60
         %71 = OpCompositeExtract %float %64 3
         %72 = OpFMul %float %71 %60
         %73 = OpCompositeExtract %v4float %53 1
         %74 = OpCompositeExtract %float %73 0
         %75 = OpFMul %float %74 %61
         %76 = OpCompositeExtract %float %73 1
         %77 = OpFMul %float %76 %61
         %78 = OpCompositeExtract %float %73 2
         %79 = OpFMul %float %78 %61
         %80 = OpCompositeExtract %float %73 3
         %81 = OpFMul %float %80 %61
         %82 = OpFAdd %float %66 %75
         %83 = OpFAdd %float %68 %77
         %84 = OpFAdd %float %70 %79
         %85 = OpFAdd %float %72 %81
         %86 = OpCompositeExtract %v4float %53 2
         %87 = OpCompositeExtract %float %86 0
         %89 = OpCompositeExtract %float %86 1
         %91 = OpCompositeExtract %float %86 2
         %93 = OpCompositeExtract %float %86 3
         %95 = OpFAdd %float %82 %87
         %96 = OpFAdd %float %83 %89
         %97 = OpFAdd %float %84 %91
         %98 = OpFAdd %float %85 %93
         %99 = OpCompositeExtract %v4float %53 3
        %100 = OpCompositeExtract %float %99 0
        %102 = OpCompositeExtract %float %99 1
        %104 = OpCompositeExtract %float %99 2
        %106 = OpCompositeExtract %float %99 3
        %108 = OpFAdd %float %95 %100
        %109 = OpFAdd %float %96 %102
        %110 = OpFAdd %float %97 %104
        %111 = OpFAdd %float %98 %106
        %112 = OpCompositeConstruct %v4float %108 %109 %110 %111
        %113 = OpInBoundsAccessChain %_ptr_Output_v4float %gl_Position %uint_0
               OpStore %113 %112
               OpSelectionMerge %118 None
               OpBranchConditional %54 %118 %119
         %57 = OpLabel
               OpBranch %188
        %118 = OpLabel
        %122 = OpULessThan %bool %uint_1 %51
               OpSelectionMerge %124 None
               OpBranchConditional %122 %124 %125
        %119 = OpLabel
               OpBranch %188
        %124 = OpLabel
        %126 = OpInBoundsAccessChain %_ptr_StorageBuffer_v2float %5 %uint_0 %uint_1
        %127 = OpLoad %v2float %126
        %129 = OpCompositeExtract %float %127 0
        %130 = OpFAdd %float %60 %129
        %132 = OpCompositeExtract %float %127 1
        %133 = OpFAdd %float %61 %132
        %138 = OpFMul %float %65 %130
        %140 = OpFMul %float %67 %130
        %142 = OpFMul %float %69 %130
        %144 = OpFMul %float %71 %130
        %147 = OpFMul %float %74 %133
        %149 = OpFMul %float %76 %133
        %151 = OpFMul %float %78 %133
        %153 = OpFMul %float %80 %133
        %154 = OpFAdd %float %138 %147
        %155 = OpFAdd %float %140 %149
        %156 = OpFAdd %float %142 %151
        %157 = OpFAdd %float %144 %153
        %167 = OpFAdd %float %154 %87
        %168 = OpFAdd %float %155 %89
        %169 = OpFAdd %float %156 %91
        %170 = OpFAdd %float %157 %93
        %180 = OpFAdd %float %167 %100
        %181 = OpFAdd %float %168 %102
        %182 = OpFAdd %float %169 %104
        %183 = OpFAdd %float %170 %106
        %184 = OpCompositeConstruct %v4float %180 %181 %182 %183
        %185 = OpInBoundsAccessChain %_ptr_Output_v4float %gl_Position %uint_1
               OpStore %185 %184
               OpBranch %188
        %125 = OpLabel
               OpBranch %188
        %188 = OpLabel
               OpReturn
               OpFunctionEnd
          %7 = OpFunction %void None %24
        %186 = OpLabel
               OpStore %8 %41
               OpReturn
               OpFunctionEnd

Backtrace

cargo run
   Compiling line v0.1.0 (/home/julian/lapis/onyx/shader/line)
   Compiling onyx v0.1.0 (/home/julian/lapis/onyx)
error: failed to run custom build command for `onyx v0.1.0 (/home/julian/lapis/onyx)`

Caused by:
  process didn't exit successfully: `/home/julian/lapis/target/debug/build/onyx-df1ad9db8f2d015b/build-script-build` (exit status: 1)
  --- stdout
  cargo:rerun-if-env-changed=RUSTGPU_CODEGEN_ARGS
  cargo:rerun-if-env-changed=RUSTGPU_RUSTFLAGS
  cargo:rerun-if-env-changed=RUSTGPU_CARGOFLAGS

  --- stderr
     Compiling line v0.1.0 (/home/julian/lapis/onyx/shader/line)
  error: [VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07054] The PrimitiveTriangleIndicesEXT decoration must be used with the OutputTrianglesEXT Execution Mode. 
    |
    = note: module `/home/julian/lapis/target/spirv-builder/spirv-unknown-vulkan1.4/release/deps/line.spv`

  warning: an unknown error occurred
    |
    = note: spirv-opt failed, leaving as unoptimized
    = note: module `/home/julian/lapis/target/spirv-builder/spirv-unknown-vulkan1.4/release/deps/line.spv`

  error: error:0:0 - [VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07054] The PrimitiveTriangleIndicesEXT decoration must be used with the OutputTrianglesEXT Execution Mode. 
           %indices = OpVariable %_ptr_Output__arr_v3uint_uint_1 Output
    |
    = note: spirv-val failed
    = note: module `/home/julian/lapis/target/spirv-builder/spirv-unknown-vulkan1.4/release/deps/line.spv`

  warning: `line` (lib) generated 1 warning
  error: could not compile `line` (lib) due to 2 previous errors; 1 warning emitted
  Error: BuildFailed

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions