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
- Flatten the struct into scalar/vector members for the stream input/output, or assign each member its own location
- Change the stream type to a supported one (scalar, vector, matrix, or fixed-size array)
- 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
- Use only scalar/vector/matrix/array types for vertex streams and interpolators
- Flatten custom structs into individual stream members before compiling
- Keep struct-typed data in constant/storage buffers, not vertex streams
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
- Unsupported composite type
- Unsupported type for element-wise cast
- Type not supported in SPIR-V
- spirv_to_dxil_pipeline failed; SPIR-V dumped to
- Can't OpLoad with cbuffer
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)