stride3d/stride · error · NotSupportedException

Unsupported type for element-wise cast

Error message

Unsupported type for element-wise cast: {valueType}

What it means

Thrown by Builder.Expressions.Convert in the element-wise numeric cast phase. Before emitting conversion instructions it classifies valueType as a scalar or vector to decide how to apply the element type cast; any other composite type (e.g. a raw matrix reaching this code path) is unsupported and raises NotSupportedException.

Solutions

  1. Restructure the shader to cast per-row/per-column instead of casting the whole composite.
  2. Extend Builder.Expressions.cs to decompose MatrixType into vectors before the element-wise cast.
  3. Check the call site (ConvertTexCoord/ConvertOffset etc.) to see why a matrix reached the cast and fix the source types.

Example fix

// before (shader)
int3x3 m = (int3x3)float3x3m;
// after: cast rows individually
int3 r0 = (int3)m[0]; int3 r1 = (int3)m[1]; int3 r2 = (int3)m[2];
Defensive patterns

Strategy: type-guard

Validate before calling

bool elementWiseCastSupported(SymbolType t) => t is ScalarType || t is VectorType;

Type guard

bool IsScalarOrVector(SymbolType t) => t is ScalarType || t is VectorType;

Try / catch

try { var r = builder.Convert(table, context, value, castType); }
catch (NotSupportedException e) { Log.Error(e.Message); /* fall back to per-component conversion */ }

Prevention

When it happens

Trigger: Calling Convert where the intermediate valueType after expansion is neither ScalarType nor VectorType when reaching the element-wise cast switch (e.g. castType requiring element-wise conversion of a MatrixType).

Common situations: Casting composite shader values (matrix types) between base element types such as int<->float; typically surfaces from unusual shader constructs mixing matrices with numeric conversions.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/6183e72a39bc85ed. Report an issue: GitHub.

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs:608

                        {
                            values[i] = Insert(new OpVectorShuffle(context.GetOrRegister(new VectorType(m1.BaseType, m2.Rows)), context.Bound++, values[i], values[i], new(shuffleIndices))).ResultId;
                        }
                    }
                    valueType = new VectorType(m1.BaseType, m2.Rows);
                    valueCount = m2.Columns;
                    break;
                }
        }

        if (valueType.GetElementType() != castType.GetElementType())
        {
            // Type casting
            // (process each vector one by one)
            (int elementSize, var castTypeSameSize) = valueType switch
            {
                ScalarType s => (1, (SymbolType)castType.GetElementType()),
                VectorType s => (s.Size, new VectorType(castType.GetElementType(), s.Size)),
                _ => throw new NotSupportedException($"Unsupported type for element-wise cast: {valueType}"),
            };
            for (int i = 0; i < valueCount; ++i)
            {
                var rowValue = values[i];
                if (rowValue == 0)
                    throw new InvalidOperationException($"Type conversion from {originalType} to {castType} failed during conversion (current type: {valueType})");

                var typeCasting = (valueType.GetElementType(), castType.GetElementType()) switch
                {
                    // https://learn.microsoft.com/en-us/windows/win32/direct3d9/casting-and-conversion
                    (ScalarType { Type: Scalar.Float }, ScalarType { Type: Scalar.Int }) => InsertData(new OpConvertFToS(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue)),
                    (ScalarType { Type: Scalar.Float }, ScalarType { Type: Scalar.UInt }) => InsertData(new OpConvertFToU(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue)),

                    (ScalarType { Type: Scalar.Float }, ScalarType { Type: Scalar.Boolean }) => InsertData(new OpFOrdNotEqual(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue, context.CreateConstantCompositeVectorRepeat(new FloatLiteral(new(32, true, true), 0.0, new()), elementSize).Id)),
                    (ScalarType { Type: Scalar.Int }, ScalarType { Type: Scalar.Boolean }) => InsertData(new OpINotEqual(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue, context.CreateConstantCompositeVectorRepeat(new IntegerLiteral(new(32, false, true), 0, new()), elementSize).Id)),
                    (ScalarType { Type: Scalar.UInt }, ScalarType { Type: Scalar.Boolean }) => InsertData(new OpINotEqual(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue, context.CreateConstantCompositeVectorRepeat(new IntegerLiteral(new(32, false, false), 0, new()), elementSize).Id)),

                    (ScalarType { Type: Scalar.Int }, ScalarType { Type: Scalar.Float }) => InsertData(new OpConvertSToF(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue)),

View on GitHub (pinned to 96fad776d2)