{"record":{"id":"c3720cdb805813fd","repo":"stride3d/stride","slug":"opbitcast-target-scalar-bitcasttargetscalar-is-not-supported","errorCode":null,"errorMessage":"OpBitcast target scalar {bitcastTargetScalar} is not supported","messagePattern":"OpBitcast target scalar (.+?) is not supported","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Context.Constants.cs","lineNumber":126,"sourceCode":"                // 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                    {\n                        // Note: first cast to object is important, otherwise int/float will be cast as float\n                        Specification.Op.OpSNegate => (object)(-(int)unaryOperand),\n                        Specification.Op.OpFNegate => -(float)unaryOperand,\n                        _ => throw new NotSupportedException($\"Unsupported unary op: {op}\"),\n                    };\n                    break;\n                // Binary operations","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Context.Constants.cs#L108-L144","documentation":"After computing bitcastBits (a 32-bit uint), TryGetConstantValue reinterprets them as the target scalar: only Scalar.Int, Scalar.UInt, and Scalar.Float are supported; any other target scalar (e.g. Bool, Half, Int64, or Double) throws NotSupportedException 'OpBitcast target scalar ... is not supported'.","triggerScenarios":"Constant-folding an OpBitcast whose result type is a bool, half, 64-bit int/uint, or double scalar — the target-scalar switch's `_ =>` arm throws.","commonSituations":"Bitcasting to half/double for precision tricks, or to bool from comparison-style codegen, in constant subexpressions of generated shaders.","solutions":["Restrict constant bitcasts to int/uint/float targets.","Perform half/double bitcasts at runtime (emit the OpBitcast instruction rather than folding).","Extend the target switch (e.g. Scalar.Half via bit manipulation, Scalar.Double via two 32-bit words)."],"exampleFix":"// before\nvalue = bitcastTargetScalar switch { Scalar.Int => ..., Scalar.UInt => ..., Scalar.Float => ..., _ => throw ... };\n// after\nvalue = bitcastTargetScalar switch { Scalar.Int => ..., Scalar.UInt => ..., Scalar.Float => ..., Scalar.Double => BitConverter.UInt32BitsToDoublePair(bitcastBits), _ => throw ... };","handlingStrategy":"validation","validationCode":"if (context.ReverseTypes[resultType] is ScalarType { Type: not (Scalar.Int or Scalar.UInt or Scalar.Float) }) EmitRuntimeInstruction(Specification.Op.OpBitcast);","typeGuard":"bool IsFoldableBitcastTarget(ScalarType t) => t.Type is Scalar.Int or Scalar.UInt or Scalar.Float;","tryCatchPattern":"try { folded = context.GetConstantValue(bitcastId); } catch (NotSupportedException ex) when (ex.Message.Contains(\"target scalar\")) { EmitRuntimeInstruction(Specification.Op.OpBitcast); }","preventionTips":["Restrict constant bitcasts to int/uint/float targets","Emit half/double bitcasts as runtime instructions","Validate target scalar kinds in your codegen before folding"],"tags":["spirv","bitcast","constant-folding","not-supported"],"backgroundTag":"unsupported-operation","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"}