Citra macOS M1 arm64 build

I was getting 30FPS solid 1440p on my M1 Mac Mini with the x86_64 build over Rosetta 2, but most games had some serious bugs… So I figured out how to compile Citra for arm64. As a result, the bugs that I have noticed in games like Zelda OOT3D and Majora’s Mask 3D have dissapeared. However, the performance has dipped as a result, giving me 24-27 FPS instead of the solid 30 like before. Hopefully we can see some more improvement for the arm64 macOS versions in the future.

Here are the steps that I took to compile.

Install Homebrew on arm64 macOS native

cd /opt
sudo mkdir homebrew
sudo chown -R $(whoami) /opt/homebrew
curl -L https://github.com/Homebrew/brew/tarball/master tar xz --strip 1 -C homebrew

Link arm64 Homebrew by adding these lines to ~/.zshrc

if [[ $(arch) == “arm64” ]]
then
export PATH=/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
fi

Now install compiling packages

brew install pkgconfig
brew install sdl2
brew install qt5
brew install cmake

Create clone of Citra in git

git clone --recursive https://github.com/citra-emu/citra
cd citra

Run this line or add it to ~/.zshrc

export Qt5_DIR=$(brew --prefix)/opt/qt5

Create build directory

mkdir build
cd build
cmake … -DCMAKE_OSX_ARCHITECTURES=“arm64;x86_64” -DCMAKE_BUILD_TYPE=Release

Run cmake again, this time only specifying arm64

cmake … -DCMAKE_OSX_ARCHITECTURES=“arm64” -DCMAKE_BUILD_TYPE=Release

Now execute the make command.

make -j4

System Information

  • Computer: Apple M1 Mac Mini 16GB
  • Operating System: macOS Big Sur 11.1
  • CPU: Apple M1 8-core
  • GPU: Apple M1 8-core
  • Ram: 16GB

I’m guessing this is with the software interpreter? We do have an AArch64 JIT used in the Android build, I’m not sure how much fiddling you’d need to do to get it up and running on MacOS.

not completely sure. Link Between Worlds doesn’t work at all, even with hardware options disabled. This is the settings I am currently selecting to run Majora’s Mask 3D. I know some things are broken still… but at least the game is actually playable now without the bugs/glitches. Not sure how much fiddling it would require to properly build Citra for arm64 with AArch64 Jit, probably more fiddling than I currently have time for. Hopefully someone else can make a break through.

One other thing I want to add. Using the Nightly Build 1587 x86_64 does seem to fix the bugs with the latest version and produce a smooth 30FPS… but the joystick mapping does not work. I got around the issue by using “Enjoyable” to map the controller to keyboard buttons. This is the best workaround at the moment for the M1 Macs at the moment. However one issue with “Enjoyable” is that the R and L trigger mapping isnt working. Trade-off’s… anyways, hope other people find this information useful.

The Instructions that you have put do not seem to be working, it is failing to compile continously

A few things:
With a few recent updates to our submodules, compiling citra on an ARM macOS should now be possible without workarounds like running with -DCMAKE_OSX_ARCHITECTURES=“arm64;x86_64”
You’ll also want to compile with ffmpeg decoder support when possible, and it seems like ffmpeg is supported on the m1 via brew, so you’ll want to do a brew install ffmpeg and add -DENABLE_FFMPEG_AUDIO_DECODER=ON to the compile options

So can you or someone else try to compile now and check if it works properly, without that workaround?
I don’t have access to a M1 mac to test this myself, so do tell me if something goes wrong.
I’ll copy the same instructions from the op with the modifications I suggested above

Install Homebrew on arm64 macOS native

cd /opt
sudo mkdir homebrew
sudo chown -R $(whoami) /opt/homebrew
curl -L https://github.com/Homebrew/brew/tarball/master tar xz --strip 1 -C homebrew

Link arm64 Homebrew by adding these lines to ~/.zshrc

if [[ $(arch) == “arm64” ]]
then
export PATH=/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
fi

Now install compiling packages

brew install pkgconfig
brew install sdl2
brew install qt5
brew install ffmpeg
brew install cmake

Create clone of Citra in git

git clone --recursive https://github.com/citra-emu/citra
cd citra

If you already did this step previously, you should do this instead

cd citra
git pull https://github.com/citra-emu/citra master
git submodule update

Run this line or add it to ~/.zshrc

export Qt5_DIR=$(brew --prefix)/opt/qt5

Create build directory

If you already have a build directory from a previous attempt, delete it before doing this.

mkdir build
cd build

Run cmake

cmake … -DCMAKE_OSX_ARCHITECTURES="arm64" -DCMAKE_BUILD_TYPE=Release -DENABLE_FFMPEG_AUDIO_DECODER=ON

Now execute the make command.

make -j4

So I did manage to build Citra on M1 Mac with the above instructions and can run citra-qt just fine but starting any game immediately crashes Citra (I have disabled all hardware accelerated features as well, still same result…). So no idea if the error is on my side or on Citra…

Is it a crash that generates a macos crash log? If so, can you provide it? (or the citra log, though it may not catch much)
And have you tested with CPU JIT off? Although dynarmic was updated so it compiles now, there might still be problems with it.

Well, in the end what can be done without a dev that has a M1 machine is limited, so don’t expect much.

I really haven’t tested it extensively (right now I’m not at my M1 Mac and won’t have time to test all day long), but didn’t find any option to disable CPU JIT in the settings - would I need to set it in the config file manually somewhere? If so I’ll try later in the evening.
Also I’ll see if I can find the Mac OS crash log somewhere, I remember it popped up.

I only recently bought the Mac Book Pro it’s my first Mac so I’m kind of new to the whole Mac OS eco system - I’m more familiar with Linux and Windows :slight_smile: - also I didn’t really expect much from that but just thought I’d give it a try when I saw that thread (my main Citra machine is a Linux x64 desktop…)

Ok I could make a quick test before work, I added

use_cpu_jit\default=false to the config file but it automatically reverts back to true… is there some setting anywhere else I could set? It seems I can’t turn it off…

Anyway, I wanted to add the crash log but the forum doesn’t allow such a long post.
I’ll post it somewhere else later and put the link in here (right now I need to start working…)

Edit: OK I had to add
use_cpu_jit=false
use_cpu_jit\default=false

then it worked, obviously speed is not perfect though with “Enable Hardware Renderer” and “Enable Shader JIT” it’s kind of playable (only tested a not so demanding game in Ace Attorney trilogy though…).
So it seems that definitely the CPU JIT is the culprit for the crash…

Edit 2: Yes as expected performance in more demanding games (I Tried Shin Megami Tensei IV: Apocalypse but I guess it’s similar in other games) is not that great without CPU JIT…

So i posted the crash log to pastebin: Mac Crash log Citra - Pastebin.com
It’s with CPU-JIT enabled, without CPU-JIT it’s working without failure…
Maybe this helps in analysing the problem?

For future reference, the CPU JIT option is on the configurations on General > Debug.
It’s hard to find as users normally shouldn’t touch it, with cases like these being exceptions.

Nevertheless this result would indicate that dynarmic does indeed need more work, I’ll take a look at the crash log later, and maybe contact merry.

1 Like

Oh haha that’s probably the only menu option I didn’t check :slight_smile:
Ah well, I found the option in the config file but good to know anways.
Also thank you for your hard work!

Looking at the apple crash log, it seems to be an assert that’s crashing (on purpose, something went wrong somewhere)
The assert message should show up on a citra log file (instructions here), and if my reasoning is correct the assert message is probably "Failed to allocate executable memory". Please confirm this if you can.

Looking at the code and searching around I found this Apple Developer Documentation which seems to describe what needs to be done, but I don’t know how difficult it’d be to go and implement.

The last entry in the log after the crash with CPU Jit enabled is:

[ 9.231722] Frontend <Info> citra_qt/main.cpp:BootGame:1022: Citra starting...

It seems Citra crashes faster than it can write the log file…

If you need the complete logfile let me know, then I’ll paste it somewhere

Ok, I did some work based on apple’s document on my branch here, and you can see the changes to dynarmic here. I have opened a PR and I’m waiting for code review from the dynarmic gods (merry).

If you want to test it out, you can do so by pulling the changes via the following commands:
git pull https://github.com/vitor-k/citra.git update-dynarmic
git submodule update
and then building normally.

Two suggestions that SachinV made on discord about getting more information from the assert that’s being triggered:

You can probably get the assert message if you run citra from the terminal (dynarmic prints stuff to stdout)

Alt strategy, you could ask them to compile and run just dynarmic tests

For the second one, should be somewhat straightforward:
git clone https://github.com/citra-emu/dynarmic.git
cd dynarmic
git checkout citra_merged
mkdir build
cd build
cmake … -DCMAKE_OSX_ARCHITECTURES="arm64"
make -j4
and then run dynarmic_tests via command line
you may also need to run brew install boost if you don’t have a system “boost” library already.

Thank you, I’ll try to build your patch a little later and let you know the results, if the crash still happens I’ll try to get the assert message as proposed (also I can post it to discord too if that’s easier for you)

Okay it seem something broke the M1 build on the current branch, as I did a git pull before merging your patch and now I’m unable to build it (it is without your new code…). I’m far from a git pro so I need to figure out how to revert back to the last working merge… (if you have a hint on how to do it I’d appreciate it but obviously this has nothing to to Citra itself so if not - no worries)

I get some weird errors now:

In file included from /Users/xxx/source/citra/externals/dynarmic/src/backend/A64/exception_handler_posix.cpp:15:
/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk/usr/include/ucontext.h:51:2: error: The deprecated ucontext routines require _XOPEN_SOURCE to be defined
#error The deprecated ucontext routines require _XOPEN_SOURCE to be defined
^
[ 21%] Building CXX object src/audio_core/CMakeFiles/audio_core.dir/hle/decoder.cpp.o
[ 63%] Built target crypto
[ 63%] Building CXX object src/audio_core/CMakeFiles/audio_core.dir/hle/filter.cpp.o
/Users/xxx/source/citra/externals/dynarmic/src/backend/A64/exception_handler_posix.cpp:102:80: error: member reference type 'struct __darwin_mcontext64 ’ is a pointer; did you mean to use ‘->’?
auto PC = reinterpret_cast(((ucontext_t
)raw_context)->uc_mcontext.pc);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^

/Users/xxx/source/citra/externals/dynarmic/src/backend/A64/exception_handler_posix.cpp:102:81: error: no member named ‘pc’ in ‘__darwin_mcontext64’
auto PC = reinterpret_cast(((ucontext_t*)raw_context)->uc_mcontext.pc);

I’ll try some more things and come back later with some results (hopefully)

Edit: I have no idea what I did wrong but now it works -still without patches but disregard this, the latest git version is at least compiling now

Edit2: Actually it’s not building after all - I cloned the current master in a new directory and started fresh and got the error after all. There must have been something that broke the M1 build. I’ll try now to add the patch on my own to the last working commit…

Okay, instead of fumbling around with git I just restored my TimeMachine backup from yesterday - crude but working :slight_smile:
Anyway, this is the output on the command line of the crash (without your new code vitor-k):

qt.qpa.fonts: Populating font family aliases took 220 ms. Replace uses of missing font family “Monospace” with one that exists to avoid this cost.
dynarmic assertion failed: ptr != nullptr
Message: Failed to allocate executable memorylibc++abi: terminating
zsh: abort ./citra-qt

I’ll now try to get it compiled with your patch let’s see how it goes

Edit (can’t make new reply):

When I try to follow the second suggestion I get the following build errors:

Consolidate compiler generated dependencies of target dynarmic
[ 3%] Building CXX object src/CMakeFiles/dynarmic.dir/backend/A64/a32_emit_a64.cpp.o
/Users/xxx/source/dynarmic/src/backend/A64/a32_emit_a64.cpp:295:55: error: lambda capture ‘fast_dispatch_entry_reg’ is not required to be captured for this use [-Werror,-Wunused-lambda-capture]
const auto calculate_location_descriptor = [this, fast_dispatch_entry_reg, location_descriptor_reg] {
^~~~~~~~~~~~~~~~~~~~~
/Users/xxx/source/dynarmic/src/backend/A64/a32_emit_a64.cpp:295:80: error: lambda capture ‘location_descriptor_reg’ is not required to be captured for this use [-Werror,-Wunused-lambda-capture]
const auto calculate_location_descriptor = [this, fast_dispatch_entry_reg, location_descriptor_reg] {
^~~~~~~~~~~~~~~~~~~~~
2 errors generated.
make[2]: *** [src/CMakeFiles/dynarmic.dir/backend/A64/a32_emit_a64.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs…
make[1]: *** [src/CMakeFiles/dynarmic.dir/all] Error 2
make: *** [all] Error 2

Edit 2:
So I cloned your branch vitor-k (instead of pulling it into the working directory and keep it clean) but otherwise followed your suggestions.
When I then try to build it I get lots of warnings and finally a build error. It’s too long to paste here I put it here on pastebin: [ 70%] Building CXX object src/web_service/CMakeFiles/web_service.dir/verify_log - Pastebin.com