stride3d/stride · error · NotSupportedException
Unsupported geometry stream output kind: {outputStreamType.K
Error message
Unsupported geometry stream output kind: {outputStreamType.Kind} What it means
The generator maps the GeometryStreamType's output Kind to a SPIR-V output execution mode: GeometryStreamOutputKindSDSL.Point → OutputPoints, Line → OutputLineStrip, Triangle → OutputTriangleStrip. Any other Kind value throws this NotSupportedException, preventing emission of an OpExecutionMode that SPIR-V would reject. It means the stream output topology parsed from the shader is not one of the three supported kinds.
Solutions
- Use one of the supported output topologies in the GS: Point, Line (strip), or Triangle (strip) — adjust the stream type declaration accordingly
- Check for a default/uninitialized Kind in custom GeometryStreamType construction and set it explicitly
- If a new kind is required, add a mapping arm in EntryPointWrapperGenerator.cs to the appropriate SPIR-V ExecutionMode (e.g. OutputPoints/OutputLineStrip/OutputTriangleStrip or a newer mode)
Example fix
// before (unknown kind) var streamType = new GeometryStreamType(GeometryStreamOutputKindSDSL.Unknown, elementType); // after var streamType = new GeometryStreamType(GeometryStreamOutputKindSDSL.Triangle, elementType);
Defensive patterns
Strategy: type-guard
Validate before calling
bool ok = outputStreamType.Kind is GeometryStreamOutputKindSDSL.Point
or GeometryStreamOutputKindSDSL.Line
or GeometryStreamOutputKindSDSL.Triangle; Type guard
static bool IsSupportedOutputKind(GeometryStreamType t) => t.Kind is
GeometryStreamOutputKindSDSL.Point or GeometryStreamOutputKindSDSL.Line
or GeometryStreamOutputKindSDSL.Triangle; Try / catch
try { wrapperGen.GenerateWrapper(...); }
catch (NotSupportedException ex) when (ex.Message.Contains("Unsupported geometry stream output kind"))
{
// report: GS output topology kind not in {Point, Line, Triangle}
} Prevention
- Declare GS outputs as point list, line strip, or triangle strip only
- Set GeometryStreamOutputKindSDSL.Kind explicitly when constructing GeometryStreamType programmatically
- Guard the kind before generation and fail early with a clear message
When it happens
Trigger: A geometry stream output type whose GeometryStreamOutputKindSDSL.Kind is outside {Point, Line, Triangle} — e.g. an unresolved/default kind, a kind added by a newer SDSL version (such as stream-out variants), or a GeometryStreamType constructed programmatically with an invalid kind.
Common situations: Using a custom or newly added stream output kind in SDSL not yet mapped in wrapper generation; programmatic SPIR-V/SDSL construction setting Kind to a default value; version mismatch between the parser that produces the kind and the generator that consumes it.
Related errors
- Unsupported geometry input execution mode: {executionMode}
- Unsupported StreamsKindSDSL for output parameter: {t.Kind}
- Execution mode primitive is missing for first parameter of g
- Second parameter of geometry shader must be a GeometryStream
- spirv_to_dxil_pipeline failed; SPIR-V dumped to {dumpPath} {
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/40241ffe18e40c5c.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Processing/Interfaces/Generation/EntryPointWrapperGenerator.cs:378
entryPointFunctionType.ParameterTypes[0] = entryPointFunctionType.ParameterTypes[0] with { Modifiers = ParameterModifiers.None };
entryPointFunctionType.ParameterTypes.RemoveAt(1);
context.ReplaceType(entryPointFunctionType, entryPointTypeId);
context.Add(new OpExecutionMode(entryPoint.IdRef, executionMode switch
{
ParameterModifiers.Point => ExecutionMode.InputPoints,
ParameterModifiers.Line => ExecutionMode.InputLines,
ParameterModifiers.LineAdjacency => ExecutionMode.InputLinesAdjacency,
ParameterModifiers.Triangle => ExecutionMode.Triangles,
ParameterModifiers.TriangleAdjacency => ExecutionMode.InputTrianglesAdjacency,
_ => throw new NotSupportedException($"Unsupported geometry input execution mode: {executionMode}"),
}, []));
context.Add(new OpExecutionMode(entryPoint.IdRef, outputStreamType.Kind switch
{
GeometryStreamOutputKindSDSL.Point => ExecutionMode.OutputPoints,
GeometryStreamOutputKindSDSL.Line => ExecutionMode.OutputLineStrip,
GeometryStreamOutputKindSDSL.Triangle => ExecutionMode.OutputTriangleStrip,
_ => throw new NotSupportedException($"Unsupported geometry stream output kind: {outputStreamType.Kind}"),
}, []));
arguments[0] = inputsVariable;
// Call main(inputs) without 2nd argument
buffer.Add(new OpFunctionCall(voidType, context.Bound++, entryPoint.IdRef, [arguments[0], .. arguments[2..]]));
}
}
else
{
// We assume a void returning function and Input/Output is all handled with streams
// Note: we could in the future support having Input/Output in the function signature, just like we do for HS/DS/GS
// Copy variables from input to streams struct
foreach (var stream in streamLayout.InputStreams)
{
var streamPointer = buffer.Add(new OpAccessChain(context.GetOrRegister(new PointerType(stream.Info.Type, Specification.StorageClass.Private)), context.Bound++, streamLayout.StreamsVariableId, [context.CompileConstant(stream.Info.StreamStructFieldIndex).Id])).ResultId;
var inputResult = buffer.Add(new OpLoad(context.Types[stream.Info.Type], context.Bound++, stream.Id, null, [])).ResultId;View on GitHub (pinned to 96fad776d2)