stride3d/stride · error · NotSupportedException

Unsupported shader stage: {entryPoints[i].Stage}

Error message

Unsupported shader stage: {entryPoints[i].Stage}

What it means

During DXIL compilation of a SPIR-V pipeline (spirv-cross/dxil-spirv path), each entry point's Stride ShaderStage must map to a known DXIL-SPIRV stage constant. EffectCompiler.CompileDxilPipeline only maps Vertex, Hull, Domain, Geometry, Pixel and Compute; any other ShaderStage value (or Unknown) hits the switch's throw arm and raises NotSupportedException. It is a defensive guard: the converter cannot translate a stage it has no mapping for.

Solutions

  1. Inspect the ShaderStage value in the message and confirm which stage is missing the mapping.
  2. If it's a genuinely new stage (e.g. mesh/amplification/ray tracing), add a case mapping it to the corresponding Compilers.Direct3D.ShaderStage constant in the switch at EffectCompiler.cs:608-617 (requires spirv_to_dxil support for that stage).
  3. If it's Unknown, fix the upstream code that discovers entry points so it assigns a concrete stage before calling compilation.
  4. Verify you are not using an experimental/modified effect compiler whose stage enum drifted from Stride's version; align the binaries/packages.

Example fix

// before
_ => throw new NotSupportedException($"Unsupported shader stage: {entryPoints[i].Stage}"),

// after
ShaderStage.Mesh => Compilers.Direct3D.ShaderStage.DXIL_SPIRV_SHADER_MESH,
ShaderStage.Amplification => Compilers.Direct3D.ShaderStage.DXIL_SPIRV_SHADER_TASK,
_ => throw new NotSupportedException($"Unsupported shader stage: {entryPoints[i].Stage}"),
Defensive patterns

Strategy: validation

Validate before calling

static readonly ShaderStage[] DxilSupportedStages = { ShaderStage.Vertex, ShaderStage.Hull, ShaderStage.Domain, ShaderStage.Geometry, ShaderStage.Pixel, ShaderStage.Compute };
if (entryPoints.Any(e => !DxilSupportedStages.Contains(e.Stage)))
    throw new InvalidOperationException("Entry point stage unsupported for DXIL conversion: " + string.Join(",", entryPoints.Where(e => !DxilSupportedStages.Contains(e.Stage)).Select(e => e.Stage)));

Type guard

bool IsDxilConvertible(ShaderStage s) => s is ShaderStage.Vertex or ShaderStage.Hull or ShaderStage.Domain or ShaderStage.Geometry or ShaderStage.Pixel or ShaderStage.Compute;

Try / catch

try { CompileDxilPipeline(spirv, entryPoints, bytecodes); }
catch (NotSupportedException ex) { log.Error($"Stage unsupported for DXIL: {ex.Message}"); throw new EffectCompilationException(ex.Message, ex); }

Prevention

When it happens

Trigger: CompileDxilPipeline is invoked with entryPoints whose Stage is not one of the six mapped values — e.g. ShaderStage.Unknown, Mesh/Amplification, RayTracing stages, or a garbage/default enum value — during desktop effect compilation to DXIL.

Common situations: A new Stride ShaderStage enum member added upstream but the DXIL mapping in EffectCompiler not updated; an entry point discovered from SPIR-V with an unrecognized execution model mapped to ShaderStage.Unknown; custom effect compilation code injecting entry points with an uninitialized/default stage.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/c1b10cc53e92abb4. Report an issue: GitHub.

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Compilers/EffectCompiler.cs:616

                var nameHandles = new System.Runtime.InteropServices.GCHandle[entryPoints.Count];
                try
                {
                    for (int i = 0; i < entryPoints.Count; i++)
                    {
                        nameHandles[i] = System.Runtime.InteropServices.GCHandle.Alloc(entryPointNameBuffers[i], System.Runtime.InteropServices.GCHandleType.Pinned);
                        stages[i] = new SpirvStageInput
                        {
                            words = (uint*)shaderData,
                            word_count = spirvBytecode.Length / 4,
                            stage = entryPoints[i].Stage switch
                            {
                                ShaderStage.Vertex => Compilers.Direct3D.ShaderStage.DXIL_SPIRV_SHADER_VERTEX,
                                ShaderStage.Hull => Compilers.Direct3D.ShaderStage.DXIL_SPIRV_SHADER_TESS_CTRL,
                                ShaderStage.Domain => Compilers.Direct3D.ShaderStage.DXIL_SPIRV_SHADER_TESS_EVAL,
                                ShaderStage.Geometry => Compilers.Direct3D.ShaderStage.DXIL_SPIRV_SHADER_GEOMETRY,
                                ShaderStage.Pixel => Compilers.Direct3D.ShaderStage.DXIL_SPIRV_SHADER_FRAGMENT,
                                ShaderStage.Compute => Compilers.Direct3D.ShaderStage.DXIL_SPIRV_SHADER_COMPUTE,
                                _ => throw new NotSupportedException($"Unsupported shader stage: {entryPoints[i].Stage}"),
                            },
                            entry_point_name = (byte*)nameHandles[i].AddrOfPinnedObject(),
                        };
                    }

                    if (!Spv2DXIL.spirv_to_dxil_pipeline(stages, entryPoints.Count, ValidatorVersion.DXIL_VALIDATOR_1_4, ref runtimeConf, ref logger, outputs))
                    {
                        var dumpPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), $"stride-dxil-fail-{Guid.NewGuid():N}.spv");
                        System.IO.File.WriteAllBytes(dumpPath, spirvBytecode.ToArray());
                        var diag = _spvLogSink is { Length: > 0 } sb ? sb.ToString().TrimEnd() : "(no diagnostics from spirv_to_dxil)";
                        throw new InvalidOperationException($"spirv_to_dxil_pipeline failed; SPIR-V dumped to {dumpPath}\n{diag}");
                    }

                    for (int i = 0; i < entryPoints.Count; i++)
                    {
                        var dxil = outputs[i];
                        Span<byte> dxilSpan = new(dxil.buffer, (int)dxil.size);
                        fixed (byte* dxilSpanPtr = dxilSpan)

View on GitHub (pinned to 96fad776d2)