stride3d/stride · error · NotSupportedException
Unsupported element type for min
Error message
Unsupported element type for min: {context.ReverseTypes[a.TypeId].GetElementType()} What it means
CompileMin maps min() to GLSL.FMin (float/double), GLSL.UMin (uint), or GLSL.SMin (int). An operand whose element type is none of these — e.g. bool or a newly introduced scalar type — reaches the default arm and throws NotSupportedException at IntrinsicImplementations.cs:113.
Solutions
- Call min() only with int/uint/float/double (or vectors thereof) operands.
- For bools use logical operators; convert other types with explicit casts before min().
- Extend CompileMin with a new switch arm (e.g. GLSLFMin16 for float16) if the type should be supported.
Example fix
// before bool2 b = min(b1, b2); // unsupported // after bool2 b = bool2(min(v1.x, v2.x) != 0, ...) // or use explicit comparisons
Defensive patterns
Strategy: type-guard
Validate before calling
// min supports float/double/uint/int element types only
if (aType.GetElementType() is not ScalarType { Type: Scalar.Float or Scalar.Double or Scalar.Int or Scalar.UInt })
throw new ShaderCompileHint("min requires numeric scalar element type"); Type guard
static bool IsMinSupported(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.CompileMin(table, context, builder, functionType, a, b); }
catch (NotSupportedException ex) when (ex.Message.Contains("element type for min"))
{ diagnostics.Report(location, ex.Message); } Prevention
- Use min() with int/uint/float/double operands only.
- Handle booleans with conditional logic, not min().
- Keep intrinsic dispatch tables in sync with the scalar type enum.
When it happens
Trigger: Calling min(a, b) where a's SPIR-V element scalar type is not Float, Double, UInt, or Int (e.g. bool vectors, half types not yet mapped).
Common situations: Using min() on booleans, on float16/half values before the backend supports them, or on custom scalar types added to the type system without updating intrinsics.
Related errors
- Unsupported element type for abs
- 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/e3fb0b35703586b3.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/IntrinsicImplementations.cs:113
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);
}
public override SpirvValue CompileMax(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 GLSLFMax(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), a.Id, b.Id)),
ScalarType { Type: Scalar.UInt } => builder.InsertData(new GLSLUMax(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), a.Id, b.Id)),
ScalarType { Type: Scalar.Int } => builder.InsertData(new GLSLSMax(context.GetOrRegister(functionType.ReturnType), context.Bound++, context.GetGLSL(), a.Id, b.Id)),
_ => throw new NotSupportedException($"Unsupported element type for max: {context.ReverseTypes[a.TypeId].GetElementType()}"),
};
return new(instruction);
}
public override SpirvValue CompileClamp(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, SpirvValue min, SpirvValue max, TextLocation location = default)
{View on GitHub (pinned to 96fad776d2)