stride3d/stride · error · NotSupportedException
Unsupported element type for abs
Error message
Unsupported element type for abs: {context.ReverseTypes[x.TypeId].GetElementType()} What it means
CompileAbs compiles the abs() intrinsic to GLSL.FAbs for float/double elements and GLSL.SAbs for signed/unsigned integers. If the element type of the operand is anything else (e.g. bool, half if unsupported, or a non-scalar element), the switch default throws NotSupportedException at IntrinsicImplementations.cs:99.
Solutions
- Apply abs() only to int/uint/float/double scalars or vectors of those types.
- For bools, use the value directly (booleans have no sign); for other numeric types cast first.
- If a new scalar kind must work, add an arm choosing the appropriate GLSL extended instruction in CompileAbs.
Example fix
// before bool2 b; abs(b); // unsupported // after int2 v = int2(-1, 2); int2 a = abs(v);
Defensive patterns
Strategy: type-guard
Validate before calling
// abs supports int/uint/float/double element types only
if (valueType.GetElementType() is not ScalarType { Type: Scalar.Float or Scalar.Double or Scalar.Int or Scalar.UInt })
throw new ShaderCompileHint("abs requires numeric scalar element type"); Type guard
static bool IsAbsSupported(BaseType t) => t.GetElementType() is ScalarType s && s.Type is Scalar.Float or Scalar.Double or Scalar.Int or Scalar.UInt;
Try / catch
try { result = intrinsic.CompileAbs(table, context, builder, functionType, x); }
catch (NotSupportedException ex) when (ex.Message.Contains("element type for abs"))
{ diagnostics.Report(location, ex.Message); } Prevention
- Apply abs() only to signed/unsigned ints and float/double values.
- Avoid abs() on bools; cast new scalar types (half, int16) before use.
- Extend CompileAbs whenever a new scalar type is added to the type system.
When it happens
Trigger: Calling abs() on a value whose SPIR-V element scalar type is neither Float, Double, Int, nor UInt — for example a bool vector or an exotic scalar type.
Common situations: Applying abs() to boolean or non-numeric values, or after adding a new scalar type (e.g. float16/int16) without extending the intrinsic implementation.
Related errors
- Unsupported element type for min
- Unsupported element type for max
- Unexpected type for asdouble
- Unsupported base type
- Unsupported type for non-pointer indexer
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/86d2060c404e4ca4.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/IntrinsicImplementations.cs:99
}
// Derivatives
public override SpirvValue CompileDdx(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.Op.OpDPdx, x);
public override SpirvValue CompileDdx_coarse(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.Op.OpDPdxCoarse, x);
public override SpirvValue CompileDdx_fine(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.Op.OpDPdxFine, x);
public override SpirvValue CompileDdy(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.Op.OpDPdy, x);
public override SpirvValue CompileDdy_coarse(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.Op.OpDPdyCoarse, x);
public override SpirvValue CompileDdy_fine(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.Op.OpDPdyFine, x);
public override SpirvValue CompileFwidth(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.Op.OpFwidth, x);
// Per component math
public override SpirvValue CompileAbs(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default)
{
var instruction = context.ReverseTypes[x.TypeId].GetElementType() switch
{
ScalarType { Type: Scalar.Float or Scalar.Double } => builder.InsertData(new GLSLFAbs(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), x.Id)),
ScalarType { Type: Scalar.UInt or Scalar.Int } => builder.InsertData(new GLSLSAbs(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), x.Id)),
_ => throw new NotSupportedException($"Unsupported element type for abs: {context.ReverseTypes[x.TypeId].GetElementType()}"),
};
return new(instruction);
}
public override SpirvValue CompileFloor(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLFloor, x);
public override SpirvValue CompileCeil(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLCeil, x);
public override SpirvValue CompileTrunc(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLTrunc, x);
public override SpirvValue CompileMin(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue a, SpirvValue b, TextLocation location = default)
{
var instruction = context.ReverseTypes[a.TypeId].GetElementType() switch
{
ScalarType { Type: Scalar.Float or Scalar.Double } => builder.InsertData(new GLSLFMin(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), a.Id, b.Id)),
ScalarType { Type: Scalar.UInt } => builder.InsertData(new GLSLUMin(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), a.Id, b.Id)),
ScalarType { Type: Scalar.Int } => builder.InsertData(new GLSLSMin(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), a.Id, b.Id)),
_ => throw new NotSupportedException($"Unsupported element type for min: {context.ReverseTypes[a.TypeId].GetElementType()}"),
};
return new(instruction);
}
View on GitHub (pinned to 96fad776d2)