{"record":{"id":"f10df13caf16e18d","repo":"stride3d/stride","slug":"unsupported-mul-operand-types-context-reversetypes-a-typeid","errorCode":null,"errorMessage":"Unsupported mul operand types: {context.ReverseTypes[a.TypeId]} and {context.ReverseTypes[b.TypeId]}","messagePattern":"Unsupported mul operand types: (.+?) and (.+?)","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/IntrinsicImplementations.cs","lineNumber":203,"sourceCode":"        // Version on https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-mul\n        // Note: SPIR-V and HLSL have opposite meaning for Rows/Columns and multiplication order need to be swapped\n        var result = (context.ReverseTypes[a.TypeId], context.ReverseTypes[b.TypeId]) switch\n        {\n            (ScalarType type1, ScalarType type2) => builder.InsertData(new OpFMul(a.TypeId, context.Bound++, a.Id, b.Id)),\n            (ScalarType type1, VectorType type2) => builder.InsertData(new OpVectorTimesScalar(b.TypeId, context.Bound++, b.Id, a.Id)),\n            (ScalarType type1, MatrixType type2) => builder.InsertData(new OpMatrixTimesScalar(b.TypeId, context.Bound++, b.Id, a.Id)),\n            (VectorType type1, ScalarType type2) => builder.InsertData(new OpVectorTimesScalar(a.TypeId, context.Bound++, a.Id, b.Id)),\n            (VectorType type1, VectorType type2) when type1.Size == type2.Size => builder.InsertData(new OpDot(a.TypeId, context.Bound++, a.Id, b.Id)),\n            (VectorType type1, MatrixType type2) when type1.Size == type2.Columns => builder.InsertData(new OpMatrixTimesVector(context.GetOrRegister(new VectorType(type1.BaseType, type2.Rows)), context.Bound++, b.Id, a.Id)),\n            (MatrixType type1, ScalarType type2) => builder.InsertData(new OpMatrixTimesScalar(a.TypeId, context.Bound++, a.Id, b.Id)),\n            (MatrixType type1, VectorType type2) when type1.Rows == type2.Size => builder.InsertData(new OpVectorTimesMatrix(context.GetOrRegister(new VectorType(type1.BaseType, type1.Columns)), context.Bound++, b.Id, a.Id)),\n            // This is HLSL-style so Rows/Columns meaning is swapped\n            //float2x4 = OpTypeMatrix vec4 x2 = MatrixType(Rows: 4, Columns: 2)\n            //float4x3 = OpTypeMatrix vec3 x4 = MatrixType(Rows: 3, Columns: 4)\n            //float2x3 = OpTypeMatrix vec3 x2 = MatrixType(Rows: 3, Columns: 2)\n            // mul(float2x4,float4x3) => float2x3\n            (MatrixType type1, MatrixType type2) when type1.Rows == type2.Columns => builder.InsertData(new OpMatrixTimesMatrix(context.GetOrRegister(new MatrixType(type1.BaseType, type2.Rows, type1.Columns)), context.Bound++, b.Id, a.Id)),\n            _ => throw new NotSupportedException($\"Unsupported mul operand types: {context.ReverseTypes[a.TypeId]} and {context.ReverseTypes[b.TypeId]}\"),\n        };\n\n        return new SpirvValue(result);\n    }\n\n    public override SpirvValue CompileReflect(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue i, SpirvValue n, TextLocation location = default)\n    {\n        var instruction = builder.Insert(new GLSLReflect(i.TypeId, context.Bound++, context.GetGLSL(), i.Id, n.Id));\n        return new(instruction.ResultId, instruction.ResultType);\n    }\n    public override SpirvValue CompileRefract(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue i, SpirvValue n, SpirvValue ri, TextLocation location = default)\n    {\n        var instruction = builder.Insert(new GLSLRefract(i.TypeId, context.Bound++, context.GetGLSL(), i.Id, n.Id, ri.Id));\n        return new(instruction.ResultId, instruction.ResultType);\n    }\n\n    public override SpirvValue CompileFaceforward(SymbolTable table, SpirvContext context, SpirvBuilder builder, FunctionType functionType, SpirvValue N, SpirvValue I, SpirvValue Ng, TextLocation location = default)\n    {","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/IntrinsicImplementations.cs#L185-L221","documentation":"CompileMul lowers the SDSL mul() intrinsic (HLSL-style matrix multiply) to SPIR-V OpMatrixTimesMatrix/OpVectorTimesMatrix etc. It pattern-matches on the operand type pair; if the combination (e.g. matrix-matrix with mismatched inner dimensions, or types that are neither vectors nor matrices) has no matching case, it throws NotSupportedException listing both resolved operand types.","triggerScenarios":"Calling mul(a, b) where a and b are not a valid (matrix,matrix), (vector,matrix), (matrix,vector) pair, or where the inner dimensions do not match (type1.Rows != type2.Columns for matrix-matrix).","commonSituations":"Transposed dimension assumptions from HLSL row/column conventions; multiplying a matrix by a scalar with mul instead of *; dimension typo in a floatNxM declaration; mixing float and int matrices.","solutions":["Verify the operand shapes: for mul(M1, M2) the inner dimensions must match (columns of M1 vs rows of M2 in HLSL terms).","Use explicit casts so both operands are the same base type (e.g. float matrices).","Multiply by a scalar with the * operator, not mul().","If a valid SPIR-V mapping exists that is missing, add a case to the switch in CompileMul (e.g. OpVectorTimesScalar)."],"exampleFix":"// before (SDSL)\nfloat2x4 a; float4x3 b; float3 v;\nfloat3 r = mul(mul(a, b), v); // ok only if dims align\nfloat1x1 s = mul(a, 2); // throws: unsupported operand types\n// after\nfloat2x3 r = mul(a, b);\nfloat2x4 s2 = a * 2;","handlingStrategy":"validation","validationCode":"bool IsValidMul(TypeBase a, TypeBase b) =>\n    (a, b) switch {\n        (MatrixType m1, MatrixType m2) => m1.Rows == m2.Columns,\n        (VectorType, MatrixType) => true,\n        (MatrixType, VectorType) => true,\n        _ => false };","typeGuard":"bool IsMatrixOrVector(TypeBase t) => t is MatrixType or VectorType;","tryCatchPattern":"try { result = intrinsics.CompileMul(table, ctx, builder, fnType, a, b); }\ncatch (NotSupportedException ex) { /* report operand types to shader diagnostics */ }","preventionTips":["Match HLSL mul() dimension rules (inner dims must agree)","Use * for scalar multiplication instead of mul","Keep matrix base types identical (all float or all int)"],"tags":["shader","spirv","sdsl","matrix","type-mismatch"],"backgroundTag":"incompatible-source-type","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"}