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

  1. Use one of the supported output topologies in the GS: Point, Line (strip), or Triangle (strip) — adjust the stream type declaration accordingly
  2. Check for a default/uninitialized Kind in custom GeometryStreamType construction and set it explicitly
  3. 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

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


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)