{"record":{"id":"b9305b3b9ffebd01","repo":"stride3d/stride","slug":"unsupported-element-type-for-clamp-context-reversetypes-x","errorCode":null,"errorMessage":"Unsupported element type for clamp: {context.ReverseTypes[x.TypeId].GetElementType()}","messagePattern":"Unsupported element type for clamp: (.+?)","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/IntrinsicImplementations.cs","lineNumber":137,"sourceCode":"    {\n        var instruction = context.ReverseTypes[a.TypeId].GetElementType() switch\n        {\n            ScalarType { Type: Scalar.Float or Scalar.Double } => builder.InsertData(new GLSLFMax(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), a.Id, b.Id)),\n            ScalarType { Type: Scalar.UInt } => builder.InsertData(new GLSLUMax(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), a.Id, b.Id)),\n            ScalarType { Type: Scalar.Int } => builder.InsertData(new GLSLSMax(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), a.Id, b.Id)),\n            _ => throw new NotSupportedException($\"Unsupported element type for max: {context.ReverseTypes[a.TypeId].GetElementType()}\"),\n        };\n        return new(instruction);\n    }\n\n    public override SpirvValue CompileClamp(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, SpirvValue min, SpirvValue max, TextLocation location = default)\n    {\n        var instruction = context.ReverseTypes[x.TypeId].GetElementType() switch\n        {\n            ScalarType { Type: Scalar.Float } => builder.InsertData(new GLSLFClamp(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), x.Id, min.Id, max.Id)),\n            ScalarType { Type: Scalar.UInt } => builder.InsertData(new GLSLUClamp(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), x.Id, min.Id, max.Id)),\n            ScalarType { Type: Scalar.Int } => builder.InsertData(new GLSLSClamp(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), x.Id, min.Id, max.Id)),\n            _ => throw new NotSupportedException($\"Unsupported element type for clamp: {context.ReverseTypes[x.TypeId].GetElementType()}\"),\n        };\n        return new(instruction);\n    }\n\n    public override SpirvValue CompileRadians(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLRadians, x);\n    public override SpirvValue CompileDegrees(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLDegrees, x);\n\n    public override SpirvValue CompileExp(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLExp, x);\n    public override SpirvValue CompileExp2(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLExp2, x);\n    public override SpirvValue CompileLog(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLLog, x);\n    public override SpirvValue CompileLog10(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => MultiplyConstant(table, context, builder, functionType.ReturnType, CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLLog2, x), (float)Math.Log10(2.0));\n    public override SpirvValue CompileLog2(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLLog2, x);\n    public override SpirvValue CompilePow(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, SpirvValue y, TextLocation location = default) => CompileGLSLFloatBinaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLPow, x, y);\n\n    // Vector math\n    public override SpirvValue CompileDistance(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue a, SpirvValue b, TextLocation location = default)\n    {\n        var instruction = builder.Insert(new GLSLDistance(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), a.Id, b.Id));","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/IntrinsicImplementations.cs#L119-L155","documentation":"CompileClamp lowers the SDSL clamp() intrinsic to a SPIR-V GLSL.std.450 clamp opcode (FClamp/UClamp/SClamp) chosen by the element type of the operand. When the operand's element type is not Float, UInt or Int (e.g. bool, double, 64-bit ints), no opcode variant exists and the compiler throws NotSupportedException, reporting the resolved element type for diagnosis.","triggerScenarios":"Calling clamp() in SDSL/HLSL shader code whose argument resolves to a vector/matrix/scalar whose element type is not one of float, uint, int — e.g. clamp() on a bool vector, a double value, or an unexpected type from a generic/t intrinsic instantiation.","commonSituations":"Using clamp on a half/double typed value assumed to behave like float; passing a bool result of a comparison into clamp; a generic shader function where T instantiates to an unsupported scalar; typos producing a wrong overload resolution.","solutions":["Check the operand's element type; convert to float/int/uint (e.g. cast or use asfloat) before clamp.","If clamping a double, cast to float first or implement manual min/max with supported types.","If the operand is bool, restructure logic so clamp only receives numeric values.","If you believe the element type should be supported, extend the switch in IntrinsicImplementations.CompileClamp to map the missing ScalarType to the appropriate GLSL clamp opcode."],"exampleFix":"// before (SDSL)\ndouble x = ...;\nfloat c = clamp(x, 0.0, 1.0); // throws\n// after\nfloat c = clamp((float)x, 0.0f, 1.0f);","handlingStrategy":"validation","validationCode":"bool IsClampable(SpirvContext ctx, SpirvValue v) =>\n    ctx.ReverseTypes[v.TypeId].GetElementType() is ScalarType { Type: Scalar.Float or Scalar.UInt or Scalar.Int };","typeGuard":"bool IsScalarOf(TypeBase t, Scalar k) => t.GetElementType() is ScalarType s && s.Type == k;","tryCatchPattern":"try { result = intrinsics.CompileClamp(table, ctx, builder, fnType, x, min, max); }\ncatch (NotSupportedException ex) { /* report shader source location & operand element type */ }","preventionTips":["Only call clamp on float/int/uint (vectors of) values","Cast doubles and halves to float before clamping","Check overload resolution when using generics in SDSL"],"tags":["shader","spirv","sdsl","type-mismatch"],"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"}