{"record":{"id":"6183e72a39bc85ed","repo":"stride3d/stride","slug":"unsupported-type-for-element-wise-cast-valuetype","errorCode":null,"errorMessage":"Unsupported type for element-wise cast: {valueType}","messagePattern":"Unsupported type for element-wise cast: (.+?)","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs","lineNumber":608,"sourceCode":"                        {\n                            values[i] = Insert(new OpVectorShuffle(context.GetOrRegister(new VectorType(m1.BaseType, m2.Rows)), context.Bound++, values[i], values[i], new(shuffleIndices))).ResultId;\n                        }\n                    }\n                    valueType = new VectorType(m1.BaseType, m2.Rows);\n                    valueCount = m2.Columns;\n                    break;\n                }\n        }\n\n        if (valueType.GetElementType() != castType.GetElementType())\n        {\n            // Type casting\n            // (process each vector one by one)\n            (int elementSize, var castTypeSameSize) = valueType switch\n            {\n                ScalarType s => (1, (SymbolType)castType.GetElementType()),\n                VectorType s => (s.Size, new VectorType(castType.GetElementType(), s.Size)),\n                _ => throw new NotSupportedException($\"Unsupported type for element-wise cast: {valueType}\"),\n            };\n            for (int i = 0; i < valueCount; ++i)\n            {\n                var rowValue = values[i];\n                if (rowValue == 0)\n                    throw new InvalidOperationException($\"Type conversion from {originalType} to {castType} failed during conversion (current type: {valueType})\");\n\n                var typeCasting = (valueType.GetElementType(), castType.GetElementType()) switch\n                {\n                    // https://learn.microsoft.com/en-us/windows/win32/direct3d9/casting-and-conversion\n                    (ScalarType { Type: Scalar.Float }, ScalarType { Type: Scalar.Int }) => InsertData(new OpConvertFToS(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue)),\n                    (ScalarType { Type: Scalar.Float }, ScalarType { Type: Scalar.UInt }) => InsertData(new OpConvertFToU(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue)),\n\n                    (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)),\n                    (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)),\n                    (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)),\n\n                    (ScalarType { Type: Scalar.Int }, ScalarType { Type: Scalar.Float }) => InsertData(new OpConvertSToF(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue)),","sourceCodeStart":590,"sourceCodeEnd":626,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs#L590-L626","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Restructure the shader to cast per-row/per-column instead of casting the whole composite.","Extend Builder.Expressions.cs to decompose MatrixType into vectors before the element-wise cast.","Check the call site (ConvertTexCoord/ConvertOffset etc.) to see why a matrix reached the cast and fix the source types."],"exampleFix":"// before (shader)\nint3x3 m = (int3x3)float3x3m;\n// after: cast rows individually\nint3 r0 = (int3)m[0]; int3 r1 = (int3)m[1]; int3 r2 = (int3)m[2];","handlingStrategy":"type-guard","validationCode":"bool elementWiseCastSupported(SymbolType t) => t is ScalarType || t is VectorType;","typeGuard":"bool IsScalarOrVector(SymbolType t) => t is ScalarType || t is VectorType;","tryCatchPattern":"try { var r = builder.Convert(table, context, value, castType); }\ncatch (NotSupportedException e) { Log.Error(e.Message); /* fall back to per-component conversion */ }","preventionTips":["Only cast scalars and vectors element-wise; decompose matrices first.","Avoid composite numeric retype casts in shaders.","If you need matrix retype, cast each row/column separately."],"tags":["spirv","unsupported-type","element-wise-cast","shader-compilation"],"backgroundTag":"unsupported-operation","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}