{"record":{"id":"1c5184dd8d7b1d98","repo":"stride3d/stride","slug":"unsupported-type-for-location-counting-type","errorCode":null,"errorMessage":"Unsupported type for location counting: {type}","messagePattern":"Unsupported type for location counting: (.+?)","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Spirv/Processing/Interfaces/InterfaceProcessor.cs","lineNumber":634,"sourceCode":"                    }\n                }\n            }\n            inputStreams = [];\n            outputStreams = [];\n            patchInputStreams = [];\n            patchOutputStreams = [];\n\n            var stage = ExecutionModelToStageId(executionModel);\n            foreach (var stream in streams)\n            {\n                int RequiredLocations(SymbolType type)\n                {\n                    return type switch\n                    {\n                        ScalarType or VectorType => 1,\n                        MatrixType m => m.Columns,\n                        ArrayType a => a.Size,\n                        _ => throw new NotSupportedException($\"Unsupported type for location counting: {type}\"),\n                    };\n                }\n\n                if (stream.Value.Input)\n                {\n                    var variableId = context.Bound++;\n                    var variableType = stream.Value.Type;\n                    if (!ProcessBuiltinsDecoration(variableId, StreamVariableType.Input, stream.Value.Semantic, ref variableType))\n                    {\n                        if (stream.Value.InputLayoutLocation == null)\n                        {\n                            stream.Value.InputLayoutLocation = inputLayoutLocationCount;\n                            inputLayoutLocationCount += RequiredLocations(variableType);\n                        }\n                        context.Add(new OpDecorate(variableId, Decoration.Location, [stream.Value.InputLayoutLocation.Value]));\n                        if (stream.Value.Semantic != null)\n                            context.Add(new OpDecorateString(variableId, Decoration.UserSemantic, stream.Value.Semantic));\n                    }","sourceCodeStart":616,"sourceCodeEnd":652,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Spirv/Processing/Interfaces/InterfaceProcessor.cs#L616-L652","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nstruct LightData { float3 Pos; float Intensity; }\n[Color] public LightData streamData; // struct stream -> NotSupported\n// after\n[Color] public float4 streamDataPos;\n[Color] public float streamDataIntensity;","handlingStrategy":"type-guard","validationCode":"static bool IsSupportedStreamType(Type t) =>\n    t.IsPrimitive || t == typeof(Half) ||\n    (t.IsArray && t.GetArrayRank() == 1) ||\n    (t.IsValueType && !t.IsPrimitive && t.GetFields().All(f => f.FieldType.IsPrimitive)); // structs must be flattened\n","typeGuard":"static bool IsFlatStreamable<T>() =>\n    typeof(T) == typeof(float) || typeof(T) == typeof(int) || typeof(T) == typeof(uint) ||\n    typeof(T) == typeof(double) || typeof(T) == typeof(Half) || typeof(T).IsArray;\n","tryCatchPattern":null,"preventionTips":["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"],"tags":["spirv","shader-compilation","unsupported-type"],"backgroundTag":"unsupported-dtype","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}