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
- Inspect the ShaderStage value in the message and confirm which stage is missing the mapping.
- 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).
- If it's Unknown, fix the upstream code that discovers entry points so it assigns a concrete stage before calling compilation.
- 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
- Keep the ShaderStage->DXIL stage mapping in sync when adding new ShaderStage enum values.
- Filter entry points to DXIL-supported stages before invoking pipeline conversion.
- Add a unit test iterating all ShaderStage values against the mapping.
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
- spirv_to_dxil_pipeline failed; SPIR-V dumped to {dumpPath} {
- Could not compile shader. See error messages:
- D3D12 shader compilation is not supported on this platform
- Can't OpLoad with cbuffer
- Unsupported symbol type: {symbolType}
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)