stride3d/stride · error · InvalidOperationException
Unexpected type for asdouble
Error message
Unexpected type {inputType} for asdouble What it means
CompileAsdouble implements the asdouble intrinsic by packing two 32-bit integers into a uint2 and bitcasting to double. If the input value's type is not one of the supported integer forms (uint/uint2 from asuint pairs), the method exhausts its branches and throws InvalidOperationException at IntrinsicImplementations.cs:55.
Solutions
- Pass the two 32-bit halves as uints: `asdouble(asuint(low), asuint(high))` or a uint2 pair.
- Do not pass float/double inputs to asdouble; convert to uint first with asuint.
- If other input types should be supported, add a branch in CompileAsdouble before the final throw.
Example fix
// before double d = asdouble(myFloat); // after uint2 packed = asuint(doubleValue); double d = asdouble(packed.x, packed.y);
Defensive patterns
Strategy: type-guard
Validate before calling
// asdouble requires uint (or uint2) input produced by asuint
if (input is not (ScalarType { Type: Scalar.UInt } or VectorType { BaseType: ScalarType { Type: Scalar.UInt } }))
throw new ShaderCompileHint("asdouble expects uint low/high pair"); Type guard
static bool IsUintValue(BaseType t) => t.GetElementType() is ScalarType { Type: Scalar.UInt }; Try / catch
try { result = CompileIntrinsic("asdouble", args, table, context, builder); }
catch (InvalidOperationException ex) when (ex.Message.Contains("for asdouble"))
{ diagnostics.Report(location, ex.Message); } Prevention
- Always derive asdouble inputs via asuint().
- Never pass float/double/int directly to asdouble.
- Document supported intrinsic signatures alongside the implementation.
When it happens
Trigger: Calling asdouble(x) with a float, double, int, vector-of-float, or any type other than the expected uint / uint2 low-high pair.
Common situations: Calling asdouble on a float variable, passing a scalar when a two-component pair is required, or on int inputs instead of the uint pair produced by asuint.
Related errors
- Unsupported element type for abs
- Unsupported element type for min
- Unsupported element type for max
- Unsupported base type
- Unsupported type for non-pointer indexer
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/5f9d5a4a19ed7d39.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/IntrinsicImplementations.cs:55
var packed = builder.Insert(new OpCompositeConstruct(uint2Type, context.Bound++, [x.Id, y.Id]));
var result = builder.Insert(new OpBitcast(doubleType, context.Bound++, packed.ResultId));
return new(result.ResultId, result.ResultType);
}
else if (inputType is VectorType v)
{
var uintType = context.GetOrRegister(ScalarType.UInt);
var components = new int[v.Size];
for (int i = 0; i < v.Size; i++)
{
var xi = builder.Insert(new OpCompositeExtract(uintType, context.Bound++, x.Id, [i]));
var yi = builder.Insert(new OpCompositeExtract(uintType, context.Bound++, y.Id, [i]));
var packed = builder.Insert(new OpCompositeConstruct(uint2Type, context.Bound++, [xi.ResultId, yi.ResultId]));
components[i] = builder.Insert(new OpBitcast(doubleType, context.Bound++, packed.ResultId)).ResultId;
}
var result = new SpirvValue(builder.InsertData(new OpCompositeConstruct(context.GetOrRegister(functionType.ReturnType), context.Bound++, [.. components])));
return result;
}
throw new InvalidOperationException($"Unexpected type {inputType} for asdouble");
}
public override SpirvValue CompileAsfloat16(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileBitcastCall(table, context, builder, functionType.ReturnType, x);
public override SpirvValue CompileAsint16(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileBitcastCall(table, context, builder, functionType.ReturnType, x);
public override SpirvValue CompileAsuint16(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileBitcastCall(table, context, builder, functionType.ReturnType, x);
// Trigo
public override SpirvValue CompileSin(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLSin, x);
public override SpirvValue CompileSinh(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLSinh, x);
public override SpirvValue CompileAsin(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLAsin, x);
public override SpirvValue CompileCos(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLCos, x);
public override SpirvValue CompileCosh(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLCosh, x);
public override SpirvValue CompileAcos(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLAcos, x);
public override SpirvValue CompileTan(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLTan, x);
public override SpirvValue CompileTanh(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLTanh, x);
public override SpirvValue CompileAtan(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, TextLocation location = default) => CompileGLSLFloatUnaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLAtan, x);
public override SpirvValue CompileAtan2(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, SpirvValue y, TextLocation location = default) => CompileGLSLFloatBinaryCall(table, context, builder, functionType.ReturnType, Specification.GLSLOp.GLSLAtan2, x, y);
public override SpirvValue CompileSincos(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue x, SpirvValue s, SpirvValue c, TextLocation location = default)
{View on GitHub (pinned to 96fad776d2)