{"record":{"id":"4a58725eab0e5739","repo":"stride3d/stride","slug":"opbitcast-operand-type-bitcastoperand-gettype-is-not","errorCode":null,"errorMessage":"OpBitcast operand type {bitcastOperand.GetType()} is not supported","messagePattern":"OpBitcast operand type (.+?) is not supported","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Context.Constants.cs","lineNumber":119,"sourceCode":"                        Specification.Op.OpConvertFToS => (object)(int)(float)convertOperand,\n                        Specification.Op.OpConvertFToU => (uint)(float)convertOperand,\n                        Specification.Op.OpConvertSToF => (float)(int)convertOperand,\n                        Specification.Op.OpConvertUToF => (float)(uint)convertOperand,\n                        _ => throw new NotSupportedException($\"Unsupported conversion op: {op}\"),\n                    };\n                    break;\n                // Bitcast: reinterpret the operand's bits as the target scalar type.\n                case Specification.Op.OpBitcast:\n                    if (!TryGetConstantValue(i.Data.Memory.Span[4], out var bitcastOperand, out _))\n                        return false;\n                    if (ReverseTypes[resultType] is not ScalarType { Type: var bitcastTargetScalar })\n                        throw new NotSupportedException($\"OpBitcast result type {ReverseTypes[resultType]} is not a scalar\");\n                    var bitcastBits = bitcastOperand switch\n                    {\n                        int v => (uint)v,\n                        uint v => v,\n                        float v => BitConverter.SingleToUInt32Bits(v),\n                        _ => throw new NotSupportedException($\"OpBitcast operand type {bitcastOperand.GetType()} is not supported\"),\n                    };\n                    value = bitcastTargetScalar switch\n                    {\n                        Scalar.Int => (object)(int)bitcastBits,\n                        Scalar.UInt => bitcastBits,\n                        Scalar.Float => BitConverter.UInt32BitsToSingle(bitcastBits),\n                        _ => throw new NotSupportedException($\"OpBitcast target scalar {bitcastTargetScalar} is not supported\"),\n                    };\n                    break;\n                // Unary operations\n                case Specification.Op.OpSNegate:\n                case Specification.Op.OpFNegate:\n                    if (!TryGetConstantValue(i.Data.Memory.Span[4], out var unaryOperand, out var unaryOperandTypeId))\n                        return false;\n                    if (unaryOperandTypeId != resultType)\n                        return false;\n                    value = op switch\n                    {","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Context.Constants.cs#L101-L137","documentation":"For OpBitcast folding, the constant operand must be an int, uint, or float (32-bit values whose bits are reinterpreted); any other operand type — e.g. a double, long, bool, or composite constant — throws NotSupportedException naming the operand's runtime type. Only single-precision bit reinterpretation is implemented.","triggerScenarios":"Constant-folding an OpBitcast whose operand constant is a double/long/Half value (i.e. not a 32-bit scalar), so the operand switch's `_ =>` arm throws.","commonSituations":"Bitcasting double-precision constants or 64-bit integers (common in hashing/random-number shader code) on constant expressions; Half constants flowing into bitcast expressions.","solutions":["Use 32-bit operand constants (int/uint/float) for bitcasts.","Handle 64-bit bitcasts manually by splitting into two 32-bit constants before the bitcast.","Extend the operand switch with double/long arms (using BitConverter.DoubleToInt64Bits / partitioning into words)."],"exampleFix":"// before\nvar bits = context.Bitcast(doubleConst, uintType); // NotSupported: operand is double\n// after\nvar lo = context.Bitcast((uint)(long)doubleBitsLo, uintType); // split 64-bit into 32-bit words","handlingStrategy":"type-guard","validationCode":"if (bitcastOperand is not (int or uint or float)) EmitRuntimeInstruction(Specification.Op.OpBitcast); // only 32-bit operands fold","typeGuard":"bool Is32BitOperand(object o) => o is int or uint or float;","tryCatchPattern":"try { folded = context.GetConstantValue(bitcastId); } catch (NotSupportedException ex) when (ex.Message.Contains(\"operand type\")) { EmitRuntimeInstruction(Specification.Op.OpBitcast); }","preventionTips":["Use 32-bit constants for bitcasts; split 64-bit values into two words","Convert double/half constants to float or uint before bitcasting in constant expressions","Document which operand widths the folding path supports"],"tags":["spirv","bitcast","constant-folding","type-mismatch"],"backgroundTag":"unsupported-dtype","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}