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

  1. Inspect the SPIR-V buffer and fix the OpTypeFloat instruction so Width is 16, 32, or 64 (e.g. with spirv-val / spirv-dis).
  2. Validate the buffer with the SPIR-V validator before calling ParseFromBuffer so malformed types are rejected upstream.
  3. If you legitimately need another width, extend the switch in ConstantExpression.cs:117 to map the width to a literal type.
  4. 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

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


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)