From 7b2563ee8cfbd27542e7a9ae338b0932d48599d4 Mon Sep 17 00:00:00 2001 From: wendlinga Date: Wed, 15 Apr 2026 12:54:39 -0700 Subject: [PATCH 1/5] Update rt64 submodule to pick up Metal crash fix for Intel Mac AMD GPU Points rt64 to wendlinga/rt64:fix/apple-clang which updates plume to call setArgumentBuffer() before setBuffer() on Tier2/non-Metal3 hardware. --- lib/rt64 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rt64 b/lib/rt64 index f0d8c9f..25a6017 160000 --- a/lib/rt64 +++ b/lib/rt64 @@ -1 +1 @@ -Subproject commit f0d8c9f29b579a143744f76c222899dc82c12e81 +Subproject commit 25a60175a4ce45c04f515b682588eb8bececb31c From 10c0cc64cebca11df28fae58c96d9a0faac19e3c Mon Sep 17 00:00:00 2001 From: wendlinga Date: Wed, 15 Apr 2026 13:38:35 -0700 Subject: [PATCH 2/5] Suppress -Wincompatible-pointer-types in patches Makefile Clang 21+ promotes -Wincompatible-pointer-types to a hard error in C mode. Several patch files pass Mtx*/float(*)[4] and similar type-mismatched pointers that the original MIPS compiler accepted silently. Add -Wno-incompatible-pointer-types to keep the existing implicit-cast patterns building with newer LLVM/Clang. This mirrors the existing -Wno-cast-function-type-mismatch flag already present. --- patches/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/Makefile b/patches/Makefile index 189ada2..639b2b1 100644 --- a/patches/Makefile +++ b/patches/Makefile @@ -6,7 +6,7 @@ LD ?= ld.lld GBI_DEFINE := -DF3DEX_GBI CFLAGS := -target mips -mips2 -mabi=32 -O2 -G0 -mno-abicalls -mno-odd-spreg -mno-check-zero-division \ -fomit-frame-pointer -ffast-math -fno-unsafe-math-optimizations -fno-builtin-memset -funsigned-char -fno-builtin-sinf -fno-builtin-cosf \ - -Wall -Wextra -Wno-incompatible-library-redeclaration -Wno-unused-parameter -Wno-unknown-pragmas -Wno-unused-variable -Wno-missing-braces -Wno-unsupported-floating-point-opt -Wno-cast-function-type-mismatch -Werror=pointer-bool-conversion + -Wall -Wextra -Wno-incompatible-library-redeclaration -Wno-unused-parameter -Wno-unknown-pragmas -Wno-unused-variable -Wno-missing-braces -Wno-unsupported-floating-point-opt -Wno-cast-function-type-mismatch -Wno-incompatible-pointer-types -Werror=pointer-bool-conversion CPPFLAGS := -nostdinc -D_LANGUAGE_C -DMIPS -I ../lib/bk-decomp/include -I ../lib/bk-decomp/include/2.0L -I ../lib/bk-decomp/include/2.0L/PR -I../lib/rt64/include -I../lib/N64ModernRuntime/ultramodern/include $(GBI_DEFINE) LDFLAGS := -nostdlib -T patches.ld -T syms.ld -Map patches.map --unresolved-symbols=ignore-all --emit-relocs From b2d6659f36d7e8e122bb499ec04e818ef407e33c Mon Sep 17 00:00:00 2001 From: wendlinga Date: Wed, 15 Apr 2026 14:07:21 -0700 Subject: [PATCH 3/5] Update rt64 submodule to rebased plume fix/apple-clang --- lib/rt64 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rt64 b/lib/rt64 index 25a6017..a72accc 160000 --- a/lib/rt64 +++ b/lib/rt64 @@ -1 +1 @@ -Subproject commit 25a60175a4ce45c04f515b682588eb8bececb31c +Subproject commit a72accc24177d53dd094ae522b86611e57962596 From f82dc70cab51db1f6994e05272a72b61957f1dd8 Mon Sep 17 00:00:00 2001 From: wendlinga Date: Wed, 15 Apr 2026 14:14:28 -0700 Subject: [PATCH 4/5] =?UTF-8?q?Add=20BUILDING=5FINTEL=5FMAC.md=20=E2=80=94?= =?UTF-8?q?=20build=20guide=20for=20Intel=20Mac=20AMD=20GPU?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BUILDING_INTEL_MAC.md | 155 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 BUILDING_INTEL_MAC.md diff --git a/BUILDING_INTEL_MAC.md b/BUILDING_INTEL_MAC.md new file mode 100644 index 0000000..5741274 --- /dev/null +++ b/BUILDING_INTEL_MAC.md @@ -0,0 +1,155 @@ +# Building on Intel Mac (AMD GPU) + +This documents the changes required to build and run `BanjoRecompiled` on an +Intel Mac with an AMD Radeon GPU. By default the app crashes at launch on this +hardware due to a bug in how Metal argument buffers are set up. + +Tested on: Intel MacBook Pro, AMD Radeon 555X (AMDMTLBronzeDriver), macOS 15.7.4. + +--- + +## Toolchain + +| Tool | Version | Use | +|------|---------|-----| +| Apple Clang (Xcode) | 16.0 | Host C++/ObjC/Metal compilation | +| Homebrew LLVM | 22 | MIPS cross-compilation for `patches/` only | +| Homebrew lld | 22 | MIPS linker for `patches/` only | +| Homebrew zlib | any | Runtime dependency for `dxc-macos` | + +Apple Clang does not include a MIPS backend, so Homebrew LLVM remains +necessary for the `patches/` directory. It is not used for any host code. + +--- + +## One-time setup + +### 1. Install Xcode + +Full Xcode (not just Command Line Tools) is required for the `metal` shader +compiler. + +```sh +# Install via xcodes (recommended) or from the App Store +brew install --cask xcodes +xcodes install # pick the latest stable release +sudo xcode-select -s /Applications/Xcode.app/Contents/Developer +``` + +### 2. Install Homebrew tools + +```sh +brew install llvm lld zlib cmake ninja +brew install rust # for bk_rom_decompress +``` + +### 3. Create the dxc libz symlink + +`dxc-macos` (the shader compiler bundled with rt64) looks for `libz.dylib` via +its rpath. macOS only ships libz in the dyld shared cache — there is no +standalone file. Create the symlink once after cloning: + +```sh +mkdir -p lib/rt64/src/contrib/dxc/bin/lib/zlib.net/v1/lib +ln -s /usr/local/opt/zlib/lib/libz.dylib \ + lib/rt64/src/contrib/dxc/bin/lib/zlib.net/v1/lib/libz.dylib +``` + +--- + +## Configure and build + +```sh +# Create the resources directory (required before first build — see note below) +mkdir -p build/resources + +cmake -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DPATCHES_C_COMPILER=/usr/local/opt/llvm/bin/clang \ + -DPATCHES_LD=/usr/local/opt/lld/bin/ld.lld + +cmake --build build --target BanjoRecompiled -j$(sysctl -n hw.ncpu) +``` + +No `CMAKE_C_COMPILER` or `CMAKE_CXX_COMPILER` flags are needed — CMake picks +up Apple Clang from Xcode automatically. + +> **Note on `mkdir -p build/resources`:** `apple_bundle.cmake` runs +> `iconutil -o resources/AppIcon.icns` without first creating the `resources/` +> directory. The directory must exist before the first build or iconutil will +> fail with "Failed to generate ICNS." + +The finished app bundle will be at `build/BanjoRecompiled.app`. + +--- + +## Source changes on this branch + +### 1. Metal crash fix — `lib/rt64/src/contrib/plume/plume_metal.cpp` + +**Root cause:** On macOS 11+, all GPUs are reported as Metal Argument Buffers +Tier 2. The `MetalDescriptorSet` constructor therefore skips calling +`setArgumentBuffer()` on the argument encoder (because `useArgumentBuffersTier2 += true`). However, Intel Mac AMD GPUs do not support Metal3 / direct buffer +addresses, so `useDirectBufferAddresses` is false and execution falls into a +path that calls `argumentEncoder->setBuffer(...)` without ever binding a +backing buffer — crashing inside +`AMDMTLBronzeDriver -[BronzeMtlIndirectArgumentBufferEncoder setBuffer:offset:atIndex:]`. + +**Fix:** In `MetalDescriptorSet::setDescriptor`, call `setArgumentBuffer()` +before `setBuffer()` in the non-direct-address path: + +```cpp +// In the else-branch of `if (device->useDirectBufferAddresses)` +argumentBuffer.argumentEncoder->setArgumentBuffer(argumentBuffer.mtl, + argumentBuffer.offset); +argumentBuffer.argumentEncoder->setBuffer(nativeBuffer, + bufferDescriptor->offset, + argumentIndex); +``` + +This call is a no-op on Apple Silicon and any other Metal3-capable hardware +since those devices take the direct-address path. + +**Upstream PR:** [renderbag/plume#94](https://github.com/renderbag/plume/pull/94) + +--- + +### 2. Patches Makefile — `patches/Makefile` + +**Root cause:** Clang 21+ promotes `-Wincompatible-pointer-types` from a +warning to a hard error in C mode. The `patches/` directory is +cross-compiled for MIPS and several files contain implicit pointer type +conversions (e.g. `Mtx *` passed where `float (*)[4]` is expected) that older +compilers accepted silently. + +**Fix:** Add `-Wno-incompatible-pointer-types` to `CFLAGS` in +`patches/Makefile`. This is consistent with the existing +`-Wno-cast-function-type-mismatch` flag already present for the same reason. + +```diff +- -Wall -Wextra ... -Wno-cast-function-type-mismatch -Werror=pointer-bool-conversion ++ -Wall -Wextra ... -Wno-cast-function-type-mismatch -Wno-incompatible-pointer-types -Werror=pointer-bool-conversion +``` + +Note: this flag is only needed with LLVM 21+. With LLVM ≤ 20 or Apple Clang +(if it ever gains a MIPS backend), the original code would compile as warnings +only. + +--- + +## What was investigated but not needed + +The following issues arose when building with Homebrew LLVM 22 + the macOS +11.1 SDK (an older approach). They are **not needed** with Apple Clang + +macOS 15 SDK: + +- **`task_id_token_t` fallback** (`MTLResource.hpp`) — introduced in macOS 13 + SDK; present in macOS 15 SDK. +- **`maximumFramesPerSecond` cast** (`plume_apple.mm`) — method undeclared in + SDK 11.1 causing return type inference as `id`; properly declared in + SDK 15. +- **`fmt/format.h` missing ``** — LLVM 22's libc++ is stricter than + Apple's libc++ about implicit inclusion. +- **`rt64_texture_cache.cpp` json iterator cast** — same LLVM 22 libc++ + strictness issue with `std::char_traits`. From 74a95ef754168311eba9e941f8d34a997c73f9bb Mon Sep 17 00:00:00 2001 From: wendlinga Date: Sat, 18 Apr 2026 09:04:27 -0700 Subject: [PATCH 5/5] Update rt64 submodule to fix black screen on Intel Mac AMD GPU Texture and sampler descriptors were bound via gpuResourceID() direct writes (the Metal3 bindless path). Intel AMD GPUs (AMDMTLBronzeDriver) report Argument Buffers Tier2 but do not support the bindless pattern, causing black output after the crash fix. Updated plume (abb241f) now gates all three resource types on useDirectBufferAddresses and uses the argument encoder for textures and samplers on non-Metal3 hardware. Co-Authored-By: Claude Sonnet 4.6 --- BUILDING_INTEL_MAC.md | 35 ++++++++++++++++++++++------------- lib/rt64 | 2 +- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/BUILDING_INTEL_MAC.md b/BUILDING_INTEL_MAC.md index 5741274..1557b2b 100644 --- a/BUILDING_INTEL_MAC.md +++ b/BUILDING_INTEL_MAC.md @@ -85,31 +85,40 @@ The finished app bundle will be at `build/BanjoRecompiled.app`. ## Source changes on this branch -### 1. Metal crash fix — `lib/rt64/src/contrib/plume/plume_metal.cpp` +### 1. Metal rendering fix — `lib/rt64/src/contrib/plume/plume_metal.cpp` **Root cause:** On macOS 11+, all GPUs are reported as Metal Argument Buffers Tier 2. The `MetalDescriptorSet` constructor therefore skips calling `setArgumentBuffer()` on the argument encoder (because `useArgumentBuffersTier2 = true`). However, Intel Mac AMD GPUs do not support Metal3 / direct buffer -addresses, so `useDirectBufferAddresses` is false and execution falls into a -path that calls `argumentEncoder->setBuffer(...)` without ever binding a -backing buffer — crashing inside -`AMDMTLBronzeDriver -[BronzeMtlIndirectArgumentBufferEncoder setBuffer:offset:atIndex:]`. +addresses (`useDirectBufferAddresses` is false). -**Fix:** In `MetalDescriptorSet::setDescriptor`, call `setArgumentBuffer()` -before `setBuffer()` in the non-direct-address path: +The original code had two distinct bugs for this hardware: + +1. **Crash** — Buffer binding called `argumentEncoder->setBuffer(...)` without + first binding a backing buffer, crashing inside + `AMDMTLBronzeDriver -[BronzeMtlIndirectArgumentBufferEncoder setBuffer:offset:atIndex:]`. + +2. **Black screen** — Texture and sampler binding wrote `gpuResourceID()` values + directly into the argument buffer (the Metal3 bindless path). Intel AMD GPUs + do not support this pattern and produce black output. Textures and samplers + must also be written via the argument encoder on non-Metal3 hardware. + +**Fix:** In `MetalDescriptorSet::setDescriptor` and `bindImmutableSamplers`, +gate all three resource-type paths on `useDirectBufferAddresses` (not on the +broader `useArgumentBuffersTier2`). For buffers, textures, and samplers alike, +call `setArgumentBuffer()` before any encode operation in the non-Metal3 path: ```cpp -// In the else-branch of `if (device->useDirectBufferAddresses)` +// In the else-branch of `if (device->useDirectBufferAddresses)` — +// applies to buffers, textures, and samplers argumentBuffer.argumentEncoder->setArgumentBuffer(argumentBuffer.mtl, argumentBuffer.offset); -argumentBuffer.argumentEncoder->setBuffer(nativeBuffer, - bufferDescriptor->offset, - argumentIndex); +// then setBuffer / setTexture / setSamplerState as appropriate ``` -This call is a no-op on Apple Silicon and any other Metal3-capable hardware -since those devices take the direct-address path. +These calls are no-ops on Apple Silicon and any other Metal3-capable hardware +since those devices always take the direct-address path. **Upstream PR:** [renderbag/plume#94](https://github.com/renderbag/plume/pull/94) diff --git a/lib/rt64 b/lib/rt64 index a72accc..0ee1026 160000 --- a/lib/rt64 +++ b/lib/rt64 @@ -1 +1 @@ -Subproject commit a72accc24177d53dd094ae522b86611e57962596 +Subproject commit 0ee1026fa9b4f3fb383a0540ce4d0cbb3f15d7eb