stride3d/stride · error · NotSupportedException

Unsupported geometry input execution mode

Error message

Unsupported geometry input execution mode: {executionMode}

What it means

After reading the input primitive modifier from the first GS parameter, the generator maps it to a SPIR-V input execution mode via a switch over ParameterModifiers: Point, Line, LineAdjacency, Triangle, TriangleAdjacency. Any other modifier value (including compound or unexpected modifier flags) hits the default arm and throws this NotSupportedException. It guards against emitting an invalid OpExecutionMode.

Solutions

  1. Use exactly one recognized primitive modifier on the GS input parameter: point, line, lineadj, triangle, or triangleadj
  2. Remove any extra modifier flags accidentally combined onto the parameter (exact switch matching means In|Point will not match Point)
  3. If a new modifier kind is legitimate, extend the switch in EntryPointWrapperGenerator.cs to map it to the corresponding SPIR-V ExecutionMode

Example fix

// before (combined modifiers fail the exact match)
void GSMain(in triangle StreamsInputStream inputs, TriangleStream<GSOutput> outStream)
// after
void GSMain(triangle StreamsInputStream inputs, TriangleStream<GSOutput> outStream)
Defensive patterns

Strategy: type-guard

Validate before calling

var m = entryPointFunctionType.ParameterTypes[0].Modifiers;
bool ok = m is ParameterModifiers.Point or ParameterModifiers.Line or ParameterModifiers.LineAdjacency
    or ParameterModifiers.Triangle or ParameterModifiers.TriangleAdjacency;

Type guard

static bool IsExactPrimitiveModifier(ParameterModifiers m) => m is
    ParameterModifiers.Point or ParameterModifiers.Line or ParameterModifiers.LineAdjacency
    or ParameterModifiers.Triangle or ParameterModifiers.TriangleAdjacency; // exact, no combined flags

Try / catch

try { wrapperGen.GenerateWrapper(...); }
catch (NotSupportedException ex) when (ex.Message.Contains("Unsupported geometry input execution mode"))
{
    // report: unrecognized/combined modifier on GS input parameter
}

Prevention

When it happens

Trigger: The first parameter of a geometry shader carries a modifier that is non-None (passing the earlier check) but not one of the five recognized primitive modifiers — e.g. a combined/flag value, an 'out' modifier on the input parameter, or a custom modifier added in a newer SDSL version that this switch doesn't handle.

Common situations: Custom SDSL dialects adding new primitive modifiers; modifier flags accidentally OR-combined (e.g. In | Point) so the exact-match switch arms fail; version skew between shader parser and generator where a modifier enum was extended.

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Processing/Interfaces/Generation/EntryPointWrapperGenerator.cs:371

                if (executionMode == ParameterModifiers.None)
                    throw new InvalidOperationException("Execution mode primitive is missing for first parameter of geometry shader");

                // Extract output topology from the GeometryStreamType parameter before removing it
                var outputStreamType = ((PointerType)entryPointFunctionType.ParameterTypes[1].Type).BaseType as GeometryStreamType
                    ?? throw new InvalidOperationException("Second parameter of geometry shader must be a GeometryStreamType");

                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

View on GitHub (pinned to 96fad776d2)