When it comes to complex projects I like to focus on whatever area of technology causes me the most uncertainty or worry. Start with the big problems, solve those, and as you continue development the work gets easier and easier. I decided at this stage I really wanted to see how well Vulkan graphics work on Mac computers.
Vulkan doesn't run natively on Mac, but gets run through a translation library called MoltenVK. How well does MoltenVK actually work? There was only one way to find out...
Preparing the Development Machine
The first step was to set up a suitable development machine. The only Mac I currently own is a 2012 MacBook Pro. I had several other options to choose from:
- Use a remote service like MacInCloud to access a new Mac remotely running macOS Big Sur.
- Buy a new Mac Mini with an M1 chip ($699).
- Buy a refurbished Mac Mini ($299-499).
What are my requirements?
- Compile universal binaries for use on Intel and ARM machines.
- Metal graphics.
I found that the oldest version of Xcode that supports universal binaries is version 12.2. The requirements for running Xcode 12.2 are macOS Catalina...which happens to be the last version of OSX my 2012 MBP supports! I tried upgrading the OS with the Mac App Store but ran into trouble because the hard drive was not formatted with the new-ish APFS drive format. I tried running disk utility in a safe boot but the option to convert the file system to APFS was disabled in the program menu, no matter what I did. Finally, I created a bootable install USB drive from the Catalina installer and did a clean install of the OS from that.
I was able to download Xcode 12.2 directly from Apple instead of the App Store and it installed without a hitch. I also installed the Vulkan SDK for Mac and the demos worked fine. The limitations on this Mac appear to be about the same as an Intel integrated chip, so it is manageable (128 shader image units accessible at any time). Maybe this is improved in newer hardware. Performance with this machine in macOS Catalina is actually great. I did replace the mechanical hard drive with an SSD years ago, so that certainly helps.
Adding Support for Universal Binaries
Mac computers are currently in another big CPU architecture shift from Intel x64 to arm64. They previously did this in 2006 when they moved from PowerPC to Intel processors, and just like now, they previously used a "universal binary" for static and shared libraries and executables.
Compiling my own code for universal binaries worked with just one change. The stat64 structure seems to be removed for the ARM builds, but changing this to "stat" worked without any problems. The FreeImage texture loader plugin, on the other hand, required a full day's work before it would compile. There is a general pattern that when I am working with just my own code, everything works nicely and neatly, but when I am interfacing with other APIs productivity drops ten times. This is why I am trying to work out all this cross-platform stuff now, so that I can get it all resolved and then my productivity will skyrocket.
macOS File Access
Since Mojave, macOS has been moving in a direction of requiring the developer to explicitly request access the parts of the file system, or for the user to explicitly allow access. On one hand, it makes sense to not allow every app access to all your user files. On the other hand, this really cripples the functionality of Mac computers. ARM CPUs do no in and of themselves carry any restrictions I am aware of, but it does look like the Mac is planned to become another walled garden ecosystem like iOS.
I had to change the structure of user projects so that the project folders are included in the build. All files and subfolders in the blue folders are packaged into your Xcode application automatically, and the result is a single app file (which is really a folder) ready to publish to the Mac App Store.
However, this means the Leadwerks-style "publish" feature is not really appropriate for the new editor. Maybe there will be an optional extension that allows you to strip unused files from a project?
There are still some unanswered questions about how this will work with an editor that involves creating and modifying large numbers of files, but the behavior I have detailed above is the best for games and self-contained applications.
MacOS is now about as locked down as iOS. You cannot run code written on another machine that is not signed with a certificate, which means Apple can probably turn anyone's program off at any time, or refuse to grant permission to distribute a program. So you might want to think twice before you buy into the Mac ecosystem.
Integration with the MoltenVK library actually went pretty smoothly. However, importing the library into an Xcode project will produce an error like "different teamID for imported library" unless you add yet another setting to your entitlements ilst, "com.apple.security.cs.disable-library-validation" and set it to YES.
I was disappointed to see the maximum accessible textures per shader are 16 on my Nvidia GEForce 750, but a fallback will need to be written for this no matter what because Intel integrated graphics chips have the same issue.
Finally, after years of wondering whether it worked and months of work, I saw the beautiful sight of a plain blue background rendered with Metal:
It looks simple, but now that I have the most basic Vulkan rendering working on Mac things will get much easier from here on out.