stride3d/stride · error · NotImplementedException
Unsupported float width {type.Width}
Error message
Unsupported float width {type.Width} What it means
ConstantExpression.ParseInstruction throws this NotImplementedException when parsing an OpConstant/OpSpecConstant whose result type is an OpTypeFloat with a Width other than 16, 32, or 64. The SPIR-V parser only knows how to materialize half, float, and double literals into a FloatConstExpr; any other declared float width (e.g. a malformed or exotic buffer) cannot be converted to a .NET double, so the library fails fast rather than silently corrupting the constant value.
Solutions
- Inspect the SPIR-V buffer and fix the OpTypeFloat instruction so Width is 16, 32, or 64 (e.g. with spirv-val / spirv-dis).
- Validate the buffer with the SPIR-V validator before calling ParseFromBuffer so malformed types are rejected upstream.
- If you legitimately need another width, extend the switch in ConstantExpression.cs:117 to map the width to a literal type.
- Check that the buffer was produced by the matching version of the Stride SPIR-V builder — older/newer toolchains may encode types differently.
Example fix
// Buffer contains a bad float type var type = new OpTypeFloat(typeInst); // Width: 48 -> throws // Fix the producer so it emits: // new OpTypeFloat(id, width: 32)
Defensive patterns
Strategy: validation
Validate before calling
static bool HasSupportedFloatWidth(SpirvBuffer buffer, int typeId)
=> buffer.TryGetInstructionById(typeId, out var t) && t.Op == Op.OpTypeFloat
&& new OpTypeFloat(t).Width is 16 or 32 or 64; Type guard
static bool IsSupportedFloatType(OpDataIndex typeInst)
=> typeInst.Op == Op.OpTypeFloat && new OpTypeFloat(typeInst).Width is 16 or 32 or 64; Try / catch
try
{
var expr = ConstantExpression.ParseFromBuffer(id, buffer, context);
}
catch (NotImplementedException ex)
{
// log unsupported float width, skip or substitute a default constant
Console.Error.WriteLine($"Unsupported constant encoding: {ex.Message}");
} Prevention
- Run spirv-val on all buffers before parsing.
- Only parse buffers produced by the Stride SPIR-V builder you compiled against.
- Never hand-edit SPIR-V type words; regenerate the buffer instead.
When it happens
Trigger: Parsing a SPIR-V buffer via ConstantExpression.ParseFromBuffer where the constant's OpTypeFloat instruction declares Width not in {16,32,64} — e.g. a corrupted hand-built SPIR-V blob, a buffer produced by a buggy custom emitter, or a non-standard float type injected by a tool.
Common situations: Feeding hand-crafted or third-party-generated SPIR-V into the SDSL parser; a producer tool writing OpTypeFloat with a wrong word-width value; fuzzing or loading truncated/misaligned SPIR-V where the width operand is read from the wrong offset.
Related errors
- Unsupported constant type {typeInst.Op}
- Unsupported OpSpecConstantOp inner op: {op}
- Cannot parse constant expression from {inst.Op}
- Cannot find type instruction for id {typeId}
- Cannot find type for composite constant type id {typeId}
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/cf0215bf810a31d9.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Core/ConstantExpression.cs:122
long val = type switch
{
{ Width: <= 32, Signedness: 0 } => (long)operand.ToLiteral<uint>(),
{ Width: <= 32, Signedness: 1 } => operand.ToLiteral<int>(),
{ Width: 64, Signedness: 0 } => (long)operand.ToLiteral<ulong>(),
{ Width: 64, Signedness: 1 } => operand.ToLiteral<long>(),
_ => throw new NotImplementedException($"Unsupported int width {type.Width}"),
};
return new IntConstExpr(val);
}
else if (typeInst.Op == Op.OpTypeFloat)
{
var type = new OpTypeFloat(typeInst);
double val = type switch
{
{ Width: 16 } => (double)operand.ToLiteral<Half>(),
{ Width: 32 } => operand.ToLiteral<float>(),
{ Width: 64 } => operand.ToLiteral<double>(),
_ => throw new NotImplementedException($"Unsupported float width {type.Width}"),
};
return new FloatConstExpr(val);
}
else
throw new NotImplementedException($"Unsupported constant type {typeInst.Op}");
}
throw new InvalidOperationException($"Cannot find type instruction for id {typeId}");
}
case Op.OpConstantStringSDSL:
{
var operand = inst.Data.Get("literalString");
return new StringConstExpr(operand.ToLiteral<string>());
}
case Op.OpGenericParameterSDSL:
case Op.OpGenericReferenceSDSL:
{View on GitHub (pinned to 96fad776d2)