{"record":{"id":"b6f5c3b345e44cc5","repo":"stride3d/stride","slug":"can-t-add-type-type","errorCode":null,"errorMessage":"Can't add type {type}","messagePattern":"Can't add type (.+?)","errorType":"validation","errorClass":"NotImplementedException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Spirv/Building/SpirvContext.Types.cs","lineNumber":155,"sourceCode":"    }\n\n    public int RegisterType(SymbolType type, int id)\n    {\n        var instruction = type switch\n        {\n            ScalarType s =>\n                s.Type switch\n                {\n                    Scalar.Void => Buffer.AddData(new OpTypeVoid(id)).IdResult,\n                    Scalar.Boolean => Buffer.AddData(new OpTypeBool(id)).IdResult,\n                    Scalar.Int => Buffer.AddData(new OpTypeInt(id, 32, 1)).IdResult,\n                    Scalar.UInt => Buffer.AddData(new OpTypeInt(id, 32, 0)).IdResult,\n                    Scalar.Int64 => Buffer.AddData(new OpTypeInt(id, 64, 1)).IdResult,\n                    Scalar.UInt64 => Buffer.AddData(new OpTypeInt(id, 64, 0)).IdResult,\n                    Scalar.Half => Buffer.AddData(new OpTypeFloat(id, 16, null)).IdResult,\n                    Scalar.Float => Buffer.AddData(new OpTypeFloat(id, 32, null)).IdResult,\n                    Scalar.Double => Buffer.AddData(new OpTypeFloat(id, 64, null)).IdResult,\n                    _ => throw new NotImplementedException($\"Can't add type {type}\")\n                },\n            VectorType v => Buffer.AddData(new OpTypeVector(id, GetOrRegister(v.BaseType), v.Size)).IdResult,\n            MatrixType m => Buffer\n                .AddData(new OpTypeMatrix(id, GetOrRegister(new VectorType(m.BaseType, m.Rows)), m.Columns))\n                .IdResult,\n            ArrayType a when a.Size != -1 || a.SizeExpression != null => RegisterArrayType(a),\n            ArrayType a when a.Size == -1 && a.SizeExpression == null => Buffer\n                .AddData(new OpTypeRuntimeArray(id, GetOrRegister(a.BaseType))).IdResult,\n            StructType st => RegisterStructuredType(st.ToId(), st),\n            FunctionType f => RegisterFunctionType(f, id),\n            PointerType p => RegisterPointerType(p, id),\n            // SampledType stores the full return type (e.g. float4, not just float) so that\n            // Texture<float> and Texture<float4> produce structurally distinct OpTypeImage during merge.\n            // ShaderMixer normalizes SampledType back to scalar before final SPIR-V emission.\n            // Do not infer a storage image format from the element type. The view decides it:\n            // RWTexture2D<float4> binds equally to R8G8B8A8_UNorm and R32G32B32A32_Float. An\n            // Unknown format makes ShaderMixer request StorageImage{Read,Write}WithoutFormat.\n            Texture1DType t => Buffer.AddData(new OpTypeImage(id, GetOrRegister(t.ReturnType), t.Dimension,","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Spirv/Building/SpirvContext.Types.cs#L137-L173","documentation":"RegisterType in SpirvContext maps SDSL scalar/vector/matrix/array types to SPIR-V type instructions. When a type falls through every known case in the first switch (an unsupported scalar kind or unexpected type shape), it throws NotImplementedException('Can't add type {type}').","triggerScenarios":"Calling RegisterType (directly or via GetOrRegister/ReplaceType) with a type whose scalar kind is not one of the handled Scalar.* values (Bool, Int8..UInt64, Half, Float, Double, etc.) or a type shape not matched in this portion of the switch.","commonSituations":"Adding a new scalar width/kind to SDSL without updating the SPIR-V backend; passing a struct/image/composite type into the scalar-only switch path.","solutions":["Check the type's Scalar kind is one supported by the SPIR-V emitter; use a supported scalar type","If you added a new Scalar kind, extend RegisterType's switch to emit the corresponding SPIR-V type instruction","For composite types, verify the correct RegisterType overload/branch is being taken (the throw here is the scalar-path fallthrough)"],"exampleFix":"// before (SpirvContext.Types.cs)\n_ => throw new NotImplementedException($\"Can't add type {type}\")\n// after\nScalar.Int8 => Buffer.AddData(new OpTypeInt(id, 8, 1)).IdResult,\n_ => throw new NotImplementedException($\"Can't add type {type}\")","handlingStrategy":"validation","validationCode":"static readonly HashSet<Scalar> SupportedScalars = new() { Scalar.Bool, Scalar.Int8, Scalar.Int16, Scalar.Int32, Scalar.Int64, Scalar.UInt8, Scalar.UInt16, Scalar.UInt32, Scalar.UInt64, Scalar.Half, Scalar.Float, Scalar.Double };\nif (type is ScalarType s && !SupportedScalars.Contains(s.Kind)) throw new NotSupportedException($\"Unsupported scalar {s.Kind}\");","typeGuard":"bool IsSupportedType(SdslType t) => t is not ScalarType s || SupportedScalars.Contains(s.Kind);","tryCatchPattern":"try { ctx.RegisterType(type); } catch (NotImplementedException ex) { logger.LogError(ex, \"Type not supported by SPIR-V backend: {Type}\", type); throw; }","preventionTips":["Keep the SDSL Scalar enum and SPIR-V type emitter in sync when adding kinds","Write a unit test registering every scalar kind","Route composite types through the correct registration path"],"tags":["shader","spirv","type-system"],"backgroundTag":"method-not-implemented","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}