Hi there, I'm facing a strange behavior when writing a function that unpacks a Float32 to two Float16.
func unpackFloat32ToFloat16(from packed: Float32) -> (Float16, Float16) {
let packedBits = packed.bitPattern
// Extract the two 16-bit patterns from the 32-bit packed value
let bits1 = UInt16(packedBits >> 16)
let bits2 = UInt16(packedBits & 0xFFFF)
// Reinterpret the 16-bit patterns as Float16
let float1 = Float16(bitPattern: bits1)
let float2 = Float16(bitPattern: bits2)
return (float1, float2)
}
This code compiles and runs normally on iOS but not on macOS (14.6.1 with Apple Silicon). On macOS the compilation error is: "Cannot convert value of type 'UInt16' to expected argument type 'UInt32'", but clearly Float16(bitPattern: bits) expect a UInt16 according to the document. Passing UInt32 is also not working and the compiler expects UInt16 instead.
I'm using Xcode-beta Version 16.0 beta 4 (16A5211f) with
$ swift --version
swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0
Thanks for your reply! Steps to reproduce this error from scratch:
Clone and configure this project. The only change I made is assigning a Development Team, Bundle Identifier and changing the Minimum Deployment version of macOS from 11.0 to 14.0.
Add the abovementioned function to the end of this file.
The compiler will produce errors at let float1 = Float16(bitPattern: bits1) and its following line.
When running in the command line with xcodebuild -project SampleApp/MetalSplatter_SampleApp.xcodeproj -scheme MetalSplatter\ SampleApp -destination "platform=macOS,arch=arm64" build, the log says it is still trying to compile for x86_64. It seems that this cannot be disabled according to this reply from the repo author. Will this be the cause of the problem?
CompileSwift normal x86_64 (in target 'MetalSplatter' from project 'MetalSplatter')
cd /Users/sunjiaming/Repositories/MetalSplatter
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend -c
# ... omitting multiple lines
/Users/sunjiaming/Repositories/MetalSplatter/MetalSplatter/Sources/SplatRenderer.swift:873:38: error: cannot convert value of type 'UInt16' to expected argument type 'UInt32'
let float1 = Float16(bitPattern: bits1)
^
UInt32( )
/Users/sunjiaming/Repositories/MetalSplatter/MetalSplatter/Sources/SplatRenderer.swift:874:38: error: cannot convert value of type 'UInt16' to expected argument type 'UInt32'
let float2 = Float16(bitPattern: bits2)
^
UInt32( )
Note that this repo use typealias Float16 = Float for x86_64 at here.
If this is the cause of the problem, since I'm only interested in building for arm64, how to entirely disable building for x86_64? I tried to set the Excluded Architectures flag but it does not work.
Yes, that's absolutely the source of your problem.
The simplest way out is to do something like:
#if arch(arm64)
let packedBits = packed.bitPattern
// Extract the two 16-bit patterns from the 32-bit packed value
let bits1 = UInt16(packedBits >> 16)
let bits2 = UInt16(packedBits & 0xFFFF)
// Reinterpret the 16-bit patterns as Float16
let float1 = Float16(bitPattern: bits1)
let float2 = Float16(bitPattern: bits2)
return (float1, float2)
#else
fatalError()
#endif
that's not ideal in general, but here, where the app already doesn't work for x86_64 (and doesn't intend to), it's fine.