stride3d/stride · error · NotSupportedException

Unsupported type for location counting

Error message

Unsupported type for location counting: {type}

What it means

While generating SPIR-V variables for each analyzed stream, InterfaceProcessor uses a helper that computes how many locations a stream's type occupies. Only scalar, vector, matrix, and array types are handled; any other type (e.g. struct or an unexpected type node) triggers NotSupportedException.

Solutions

  1. Flatten the struct into scalar/vector members for the stream input/output, or assign each member its own location
  2. Change the stream type to a supported one (scalar, vector, matrix, or fixed-size array)
  3. If it must be a struct, pass it via a constant buffer or storage buffer instead of a vertex/interpolated stream

Example fix

// before
struct LightData { float3 Pos; float Intensity; }
[Color] public LightData streamData; // struct stream -> NotSupported
// after
[Color] public float4 streamDataPos;
[Color] public float streamDataIntensity;
Defensive patterns

Strategy: type-guard

Validate before calling

static bool IsSupportedStreamType(Type t) =>
    t.IsPrimitive || t == typeof(Half) ||
    (t.IsArray && t.GetArrayRank() == 1) ||
    (t.IsValueType && !t.IsPrimitive && t.GetFields().All(f => f.FieldType.IsPrimitive)); // structs must be flattened

Type guard

static bool IsFlatStreamable<T>() =>
    typeof(T) == typeof(float) || typeof(T) == typeof(int) || typeof(T) == typeof(uint) ||
    typeof(T) == typeof(double) || typeof(T) == typeof(Half) || typeof(T).IsArray;

Prevention

When it happens

Trigger: MergeSDSL where a stream (vertex input/output) is declared with a type outside the supported set — typically a custom struct or user-defined type used as a streams input/output with a location, so the switch's default arm is reached in GenerateStreamVariables.

Common situations: Declaring a struct-typed vertex input/output in SDSL; a code-generated stream whose type resolved to an unexpected SPIR-V type node after mixin merging; using a buffer/texture type in a position where an interpolator type is expected.

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Processing/Interfaces/InterfaceProcessor.cs:634

                    }
                }
            }
            inputStreams = [];
            outputStreams = [];
            patchInputStreams = [];
            patchOutputStreams = [];

            var stage = ExecutionModelToStageId(executionModel);
            foreach (var stream in streams)
            {
                int RequiredLocations(SymbolType type)
                {
                    return type switch
                    {
                        ScalarType or VectorType => 1,
                        MatrixType m => m.Columns,
                        ArrayType a => a.Size,
                        _ => throw new NotSupportedException($"Unsupported type for location counting: {type}"),
                    };
                }

                if (stream.Value.Input)
                {
                    var variableId = context.Bound++;
                    var variableType = stream.Value.Type;
                    if (!ProcessBuiltinsDecoration(variableId, StreamVariableType.Input, stream.Value.Semantic, ref variableType))
                    {
                        if (stream.Value.InputLayoutLocation == null)
                        {
                            stream.Value.InputLayoutLocation = inputLayoutLocationCount;
                            inputLayoutLocationCount += RequiredLocations(variableType);
                        }
                        context.Add(new OpDecorate(variableId, Decoration.Location, [stream.Value.InputLayoutLocation.Value]));
                        if (stream.Value.Semantic != null)
                            context.Add(new OpDecorateString(variableId, Decoration.UserSemantic, stream.Value.Semantic));
                    }

View on GitHub (pinned to 96fad776d2)