{"record":{"id":"cb29de1a2bb79099","repo":"stride3d/stride","slug":"unsupported-element-type-for-sign-sourcetype-getelementtype","errorCode":null,"errorMessage":"Unsupported element type for sign: {sourceType.GetElementType()}","messagePattern":"Unsupported element type for sign: (.+?)","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/IntrinsicImplementations.cs","lineNumber":252,"sourceCode":"        var constant1 = builder.Convert(context, context.CompileConstant(1.0f), functionType.ReturnType);\n\n        var instruction = functionType.ReturnType.GetElementType() switch\n        {\n            ScalarType { Type: Scalar.Float } => builder.InsertData(new GLSLFClamp(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), x.Id, constant0.Id, constant1.Id)),\n            ScalarType { Type: Scalar.UInt } => builder.InsertData(new GLSLUClamp(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), x.Id, constant0.Id, constant1.Id)),\n            ScalarType { Type: Scalar.Int } => builder.InsertData(new GLSLSClamp(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), x.Id, constant0.Id, constant1.Id)),\n            _ => throw new NotSupportedException($\"Unsupported element type for saturate: {functionType.ReturnType.GetElementType()}\"),\n        };\n        return new(instruction);\n    }\n    public override SpirvValue CompileSign(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default)\n    {\n        var sourceType = context.ReverseTypes[x.TypeId];\n        var instruction = sourceType.GetElementType() switch\n        {\n            ScalarType { Type: Scalar.Float or Scalar.Double } => builder.InsertData(new GLSLFSign(x.TypeId, context.Bound++, context.GetGLSL(), x.Id)),\n            ScalarType { Type: Scalar.UInt or Scalar.Int or Scalar.UInt64 or Scalar.Int64 } => builder.InsertData(new GLSLSSign(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), x.Id)),\n            _ => throw new NotSupportedException($\"Unsupported element type for sign: {sourceType.GetElementType()}\"),\n        };\n        // FSign return float whereas HLSL sign() expects int\n        return builder.Convert(context, new(instruction), functionType.ReturnType);\n    }\n\n    public override SpirvValue CompileSmoothstep(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue a, SpirvValue b, SpirvValue x, TextLocation location = default)\n    {\n        var instruction = builder.Insert(new GLSLSmoothStep(a.TypeId, context.Bound++, context.GetGLSL(), a.Id, b.Id, x.Id));\n        return new(instruction.ResultId, instruction.ResultType);\n    }\n\n    public override SpirvValue CompileLerp(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue a, SpirvValue b, SpirvValue s, TextLocation location = default)\n    {\n        var instruction = builder.Insert(new GLSLFMix(a.TypeId, context.Bound++, context.GetGLSL(), a.Id, b.Id, s.Id));\n        return new(instruction.ResultId, instruction.ResultType);\n    }\n\n    public override SpirvValue CompileFmod(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue a, SpirvValue b, TextLocation location = default)","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/IntrinsicImplementations.cs#L234-L270","documentation":"CompileSign implements sign() using GLSL.std.450 FSign for float/double and SSign for integer types (including 64-bit), then converts the result to the expected int return type. If the source operand's element type is none of these (e.g. bool or half), no opcode applies and NotSupportedException is thrown.","triggerScenarios":"Calling sign(x) where x's element type is not float, double, int, uint, int64 or uint64 — e.g. sign of a bool, or of a struct/vector with unexpected element kind resolved from generics.","commonSituations":"sign() on a bool from a comparison; sign() on a half-precision type where the frontend kept half as a distinct scalar; generic T instantiation to an unsupported scalar.","solutions":["Cast the operand to float or int before calling sign (e.g. sign((int)x)).","Replace sign of a bool with explicit comparison logic (x ? 1 : -1).","Ensure the generic type parameter is constrained to numeric scalar types.","If the scalar kind should be supported, add a case to CompileSign mapping it to FSign/SSign."],"exampleFix":"// before (SDSL)\nbool b = a > 0;\nint s = sign(b); // throws\n// after\nint s = sign((int)(a > 0 ? 1 : -1));","handlingStrategy":"validation","validationCode":"bool IsSignable(TypeBase t) =>\n    t.GetElementType() is ScalarType { Type: Scalar.Float or Scalar.Double or Scalar.Int or Scalar.UInt or Scalar.Int64 or Scalar.UInt64 };","typeGuard":"bool IsNumericScalar(TypeBase t) => t.GetElementType() is ScalarType s && s.Type != Scalar.Bool;","tryCatchPattern":"try { result = intrinsics.CompileSign(table, ctx, builder, fnType, x); }\ncatch (NotSupportedException ex) { /* report element type; suggest cast */ }","preventionTips":["Never call sign() on bool expressions","Cast half-precision values to float before sign","Constrain generic T to numeric scalars"],"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"}