{"record":{"id":"a9b0dcde8921ace9","repo":"stride3d/stride","slug":"unsupported-constant-type-typeinst-op","errorCode":null,"errorMessage":"Unsupported constant type {typeInst.Op}","messagePattern":"Unsupported constant type (.+?)","errorType":"exception","errorClass":"NotImplementedException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Core/ConstantExpression.cs","lineNumber":127,"sourceCode":"                            { Width: 64, Signedness: 1 } => operand.ToLiteral<long>(),\n                            _ => throw new NotImplementedException($\"Unsupported int width {type.Width}\"),\n                        };\n                        return new IntConstExpr(val);\n                    }\n                    else if (typeInst.Op == Op.OpTypeFloat)\n                    {\n                        var type = new OpTypeFloat(typeInst);\n                        double val = type switch\n                        {\n                            { Width: 16 } => (double)operand.ToLiteral<Half>(),\n                            { Width: 32 } => operand.ToLiteral<float>(),\n                            { Width: 64 } => operand.ToLiteral<double>(),\n                            _ => throw new NotImplementedException($\"Unsupported float width {type.Width}\"),\n                        };\n                        return new FloatConstExpr(val);\n                    }\n                    else\n                        throw new NotImplementedException($\"Unsupported constant type {typeInst.Op}\");\n                }\n                throw new InvalidOperationException($\"Cannot find type instruction for id {typeId}\");\n            }\n\n            case Op.OpConstantStringSDSL:\n            {\n                var operand = inst.Data.Get(\"literalString\");\n                return new StringConstExpr(operand.ToLiteral<string>());\n            }\n\n            case Op.OpGenericParameterSDSL:\n            case Op.OpGenericReferenceSDSL:\n            {\n                var genParam = (OpGenericParameterSDSL)inst;\n                return new GenericParamExpr(genParam.Index, genParam.DeclaringClass);\n            }\n\n            case Op.OpConstantComposite:","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Core/ConstantExpression.cs#L109-L145","documentation":"ConstantExpression.ParseInstruction throws this NotImplementedException when an OpConstant/OpSpecConstant's result type instruction is neither OpTypeInt nor OpTypeFloat. SPIR-V constants of other types (e.g. OpTypeBool, vectors, structs) are not handled by the scalar constant branch, so the parser refuses to build a ConstantExpression for them.","triggerScenarios":"Calling ConstantExpression.ParseFromBuffer on an id whose instruction is OpConstant/OpSpecConstant but whose result-type id resolves to a type instruction like OpTypeBool, OpTypeVector, or OpTypeStruct — e.g. extracting an 'array size' or generic argument that is actually a boolean or composite constant.","commonSituations":"Shader code using a bool spec-constant where an int is expected; pointing ParseFromBuffer at the wrong id in the buffer (a composite rather than scalar constant); SPIR-V produced by another compiler that models constants with types the SDSL parser never anticipated.","solutions":["Verify with spirv-dis that the id passed to ParseFromBuffer is a scalar int/float constant, not a bool or composite.","Handle boolean constants (OpConstantTrue/OpConstantFalse) before reaching this branch — they are parsed separately as BoolConstExpr.","If the constant is composite, ensure it comes through the OpConstantComposite branch instead.","If a new scalar type must be supported, add a branch for its type op in ConstantExpression.cs:126."],"exampleFix":"// before: ParseFromBuffer(boolConstantId, ...) -> OpConstant true, type OpTypeBool -> throws\n// after: check the opcode first\nif (buffer.TryGetInstructionById(id, out var inst) && inst.Op == Op.OpConstantTrue)\n    return new BoolConstExpr(true); // or use the constant only when it is an int/float scalar","handlingStrategy":"type-guard","validationCode":"static bool IsScalarIntOrFloatConstant(SpirvBuffer buffer, int id)\n{\n    if (!buffer.TryGetInstructionById(id, out var inst)) return false;\n    if (inst.Op is not (Op.OpConstant or Op.OpSpecConstant)) return false;\n    var typeId = inst.Data.Memory.Span[1];\n    return buffer.TryGetInstructionById(typeId, out var t)\n        && t.Op is Op.OpTypeInt or Op.OpTypeFloat;\n}","typeGuard":"static bool IsScalarConstantType(OpDataIndex typeInst)\n    => typeInst.Op is Op.OpTypeInt or Op.OpTypeFloat;","tryCatchPattern":"try\n{\n    var expr = ConstantExpression.ParseFromBuffer(id, buffer, context);\n}\ncatch (NotImplementedException)\n{\n    // constant type is bool/composite; route to the appropriate parser branch or skip\n}","preventionTips":["Check the opcode of the target instruction before calling ParseFromBuffer.","Parse bool constants via OpConstantTrue/OpConstantFalse and composites via the composite branch.","Keep to scalar int/float spec constants for array sizes and generic arguments."],"tags":["spirv","shader-parsing","unsupported-operation","not-implemented"],"backgroundTag":"unsupported-operation","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"}