Repository navigation
Mac Compatibility Analysis
Audience: Programmers | Mixed
Thread Context: N/A (research/reference)
Platform/Backend Scope: macOS (Metal / MoltenVK / OpenGL), with cross-platform contrast
Deep analysis of macOS support across every subsystem — graphics, audio, input,
networking, build infrastructure, and the Metal RHI backend including hardware ray
tracing. macOS started as an experimental, partially-stubbed path and is now buildable
end-to-end with a real Metal backend; CI still runs the macOS job as
continue-on-error until the platform fully stabilizes.
This page consolidates a long series of incremental sessions into the current state and the remaining work.
-
Platform abstraction —
Platform.hdetects__APPLE__, definesSPARK_PLATFORM_MACOS, identifies Apple Clang. -
Audio —
OpenALAudioEngine.hcompiles for macOS (guard!SPARK_PLATFORM_WINDOWS); CMake probes Homebrewopenal-softand falls back to systemOpenAL.framework, definingSPARK_OPENAL_AVAILABLE=1so the engine pulls in realAL/al.h. -
Networking — POSIX sockets with
fcntl()fallback inUDPTransport.h. -
Physics — Jolt is cross-platform; Metal compute optional via
xcrun. -
Module loading —
dlopen/dlsymfallback inModuleManager.cppfor.dylib. -
Crash handling — POSIX signals +
backtrace()with macOS guards (sysctl/machsystem info). -
Console process manager — POSIX
fork/execwith macOS guards. -
Input —
InputManager.cppnow has Windows + Linux/macOS branches (SDL2 for capture). This was a critical gap in the original analysis; resolved. - Third-party deps — all support macOS (Jolt, EnTT, ImGui, AngelScript, SDL2, GLAD, OpenAL, Recast).
-
OpenGL on macOS caps at GL 4.1, while the engine targets GL 4.6 — viable as a
fallback only, not long-term.
GL_SILENCE_DEPRECATION=1is defined on Apple to keep build logs clean. -
Hardware ray tracing requires macOS 12+ and a GPU reporting
supportsRaytracing; otherwise the engine falls back to SDFGI. - The Metal RT scene path is wired but several deeper items remain (see Metal RT below).
The Metal backend is implemented, not header-only. MetalDevice.mm is a full
implementation (~70 KB on disk) alongside the MetalDevice.h interface. Supporting
Metal translation units exist:
-
MetalDevice.h/MetalDevice.mm— device, swapchain, pipeline state. -
MetalRayTracing.h/MetalRayTracing.mm— hardware ray-tracing system. -
MetalTextureReadback.h/MetalTextureReadback.mm— CPU readback of MTLTextures. -
MetalGoldenImageCapture.h/MetalGoldenImageCapture.mm— golden-image capture (anIGoldenImageCapturesubclass over the readback helper).
What the Metal device covers end-to-end:
-
MetalSwapChainowns anMTLCommandQueue;Present(vsync)submits a command buffer that callspresentDrawable:— drawables actually display. -
ConfigureMetalLayeraccepts anNSView(raw Cocoa orSDL_Metal_CreateView) or aCAMetalLayer, reusing an existing layer on the SDL path. -
SetRenderTargetsbinds up to 8 color attachments plus depth/stencil (MRT). -
ClearDepthStenciluses a clear-load render pass. - Indirect draw/dispatch via Metal's indirect-buffer API.
-
CreatePipelineStatewires blend, depth/stencil, input layout (vertex descriptor), stencil format for combined D24S8/D32S8, and pipeline debug labels. -
SetPipelineStateapplies rasterizer state (cull, winding, fill, depth bias). - Capabilities report
RayTracingBackend::HardwareMetalRTwith correct RT flags when the Apple GPU supports it.
macOS window/Metal wiring lives in a dedicated, cross-platform-safe pair:
-
Core/SparkEngineMacOS.h— declaresSpark::MacOS::helpers (ShouldPreferMetal,GetMetalWindowFlag,CreateMetalView,DestroyMetalView,GetExecutableDirectory). Safe to call on any platform — non-macOS links no-op stubs. -
Core/SparkEngineMacOS.cpp— real implementations underSPARK_PLATFORM_MACOS(<SDL_metal.h>,<mach-o/dyld.h>,RHIBridge::GetRecommendedBackend()); no-op stubs elsewhere. - The POSIX entry point (
SparkEngineLinux.cpp, "Linux + macOS") has no#ifdef __APPLE__branches — it calls the helpers. -
SparkEngineMacOS.cpplives inSparkEngineLibso both the engine exe and the test runner see the symbols.
MetalRayTracingSystem provides a working hardware RT path on capable Apple GPUs,
gated by [device supportsRaytracing] and @available(macOS 12.0, *). It compiles a
4-kernel Metal library at runtime (MTLLanguageVersion2_4) for shadows, reflections,
ambient occlusion, and global illumination.
Capabilities:
-
BLAS — real
CreateBLAS/UpdateBLAS(refit) /DestroyBLASusing primitive acceleration-structure descriptors and one-shot command buffers. -
TLAS — real
BuildTLASfrom instance descriptors (4×3 transforms, mask, hit-group offset, BLAS index). -
Kernels — shadows reconstruct world position and trace visibility; reflections
reflect off GBuffer normal with sky-gradient miss; AO uses cosine-weighted hemisphere
sampling; GI does single-bounce diffuse. Shared MSL helpers
Hash12(PRNG) andCosineHemisphere. -
Materials —
MaterialParams(albedo, emissive, roughness/metallic; 48 bytes, 16-byte aligned) uploaded as an MTLBuffer at slot 2;ShadeHitdoes Lambert + emissive. A consistent 7-slot uniform binding layout across all four kernels. -
Frame I/O —
FrameParams(invViewProj, cameraPos, lightDir, resolution),SetFrameParams/SetInputTextures/SetOutputTextures, dispatched at 8×8 threadgroups byEncodeTracePass.
-
HybridRTManager(macOS only) constructs aMetalRayTracingSystemwhen the detected backend isHardwareMetalRT;Execute'sHardwareMetalRTcase rebuilds a dirty TLAS, fillsFrameParams, dispatches the four kernels, then falls through to SDFGI so the compositor always receives data. - Mesh-push API:
PushTriangleMesh(TriangleMeshDesc)and aMeshAssetoverload route toCreateBLAS;ClearTriangleMeshes()tears everything down. Off-macOS these are guard-only no-ops. -
Graphics/HybridRT/RTSceneFeeder.{h,cpp}walks theTransform + MeshRendererECS view (same order asRenderSystem::Update), resolves meshes viaAssetPipeline, and pushes geometry; a companion populates per-instance materials in identical traversal order soMaterialParams[]index equals TLASinstance_id. -
RTMaterialAdapter.hconvertsPBRPropertiestoMaterialParams.
-
CMake presets —
macos-debug/macos-releasedefault toENABLE_METAL=ON,ENABLE_VULKAN=OFF,ENABLE_DXR=OFF,ENABLE_SDL2=ON,ENABLE_OPENGL=ON.macos-metaladds Metal explicitly;macos-moltenvkopts into Vulkan via Homebrew MoltenVK. (Current preset set verified 2026-06-08:macos-debug,macos-release,macos-metal,macos-moltenvk.) -
CMAKE_OSX_DEPLOYMENT_TARGET=11.0(Big Sur) pinned when unset — first Apple Silicon release and the Metal 3 floor for M-series. -
OBJCXX —
enable_language(OBJCXX)runs only behindSPARK_METAL_AVAILABLE;.mmglobbing is gated the same way so an OpenGL-only macOS build configures cleanly. - Frameworks — Cocoa, IOKit, CoreVideo, AudioToolbox, CoreAudio, CoreFoundation, plus Metal/Foundation for RT TUs.
-
X11 — guarded with
NOT APPLE(Cocoa via SDL2; no X11 on macOS). -
CI —
build-macosuses aninclude:matrix:(Debug, OpenGL, metal=OFF),(Release, OpenGL, metal=OFF),(Release, Metal, metal=ON). The Metal row compilesMetalDevice.mm+MetalRayTracing.mmend-to-end on every PR.brew installaddssdl2 openal-soft ccacheand best-effortmolten-vk. Job iscontinue-on-error. - Metal files are excluded from clang-format CI (
-not -path '*/Metal/*').
To bring Linux/macOS toward Windows parity in the deferred path:
-
RHIBridgehas a render-target registry:RenderTargetSlotenum (4 GBuffer + depth- HDR),
RegisterRenderTarget/GetRenderTarget, non-owning fixed-size array.
- HDR),
-
HybridRTBindingsuses raw pointers aliasing into anownedvector (Windows holds per-frameWrapNativeTexturewrappers; Linux/macOS read from the registry). - Linux/macOS GBuffer + HDR targets are created and registered in
GraphicsEngineLinux.cpp(CreatePlatformRenderTargets/ReleasePlatformRenderTargets), hooked into Initialize/Shutdown/Resize. -
RenderDeferredon Linux/macOS calls the sharedDispatchHybridRTPass.
ProcessDrawList is fully ported to non-Windows via the RHI bridge (no more
drain-without-render stub):
-
MeshAssetcarriesIRHIBuffervertex/index buffers, built byAssetPipeline::BuildRHIBuffersForMesh(Linux) post-load. -
TextureAsset::Loadon Linux decodes via stb_image and uploads through the RHI bridge. -
BindMesh/BindMaterial/DrawBoundMeshissue realSetVertexBuffer/SetIndexBuffer/SetShaderResource/DrawIndexed. -
ProcessDrawListdrains, sorts by (material, mesh), binds, and draws with profiler events.
-
Tests/TestMacOSPlatform.cpp— smoke tests forSpark::MacOS::*(run on all platforms; stub contract off-macOS, real behavior on macOS) plus HybridRT push/clear-without-init safety. -
Tests/TestMetalRayTracing.cpp— CPU-only RT tests (no MTLDevice): pre-init state,MaterialParamsFromPBR, struct layout/size,TracePassbitmask. -
Tests/TestMetalRayTracingLive.mm— the first.mmtest file; live-MTLDevicetests viaMetalDevice::Initialize(headlessMTLCreateSystemDefaultDevice), gated byif(APPLE AND SPARK_METAL_AVAILABLE). Includes BLAS/TLAS build, material round-trip, golden-capture readback. ASKIP_IF_NO_RTmacro neutralizes runners lacking hardware RT. -
Tests/TestProcessDrawListLinux.cpp— RHI buffer/texture upload + draw-list drain on NullRHI.
-
SparkEngine/Source/Graphics/RHI/Metal/MetalDevice.{h,mm}— Metal device/swapchain. -
SparkEngine/Source/Graphics/RHI/Metal/MetalRayTracing.{h,mm}— hardware RT. -
SparkEngine/Source/Graphics/RHI/Metal/MetalTextureReadback.{h,mm}— CPU readback. -
SparkEngine/Source/Graphics/RHI/Metal/MetalGoldenImageCapture.{h,mm}— golden capture. -
SparkEngine/Source/Graphics/RHI/RHIFactory.cpp— backend selection (Metal on__APPLE__). -
SparkEngine/Source/Core/Platform.h— platform/compiler detection. -
SparkEngine/Source/Core/SparkEngineMacOS.{h,cpp}— macOS window/Metal helpers. -
SparkEngine/Source/Audio/OpenALAudioEngine.h— cross-platform audio. -
SparkEngine/Source/Input/InputManager.cpp— Windows + Linux/macOS branches. -
SparkEngine/Source/Graphics/HybridRT/RTSceneFeeder.{h,cpp}— ECS RT feeder.
| Platform | Minimum | Recommended |
|---|---|---|
| Windows | Win10 x64, MSVC 19.36+, D3D11 FL 10.0 | Win11, MSVC v143/v145, D3D11 FL 11.1, D3D12+DXR |
| Linux | glibc 2.35+ x64, GCC 13+/Clang 17+, OpenGL 4.6 or Vulkan 1.3 | Ubuntu 24.04, GCC 14, Vulkan 1.3 |
| macOS | macOS 11 Big Sur, x64/ARM64, Metal 2.3 or OpenGL 4.1 | macOS 12+, Apple Silicon M2+, Metal 3 with supportsRaytracing
|
Pinned by: CMAKE_OSX_DEPLOYMENT_TARGET=11.0, cmake_minimum_required(3.25), the
MetalRayTracing.mm @available(macOS 12.0, *) gate for hardware RT. A public-facing
version of this matrix also lives at wiki/platform/System-Requirements.md.
- Reflection/AO/GI kernels could use deeper trace bodies and per-pass quality tuning.
- Per-draw constant-buffer upload (world/view/proj) on the RHI path — needs a shader-constant layout refactor with per-backend slot coordination.
- GPU particle system, FSR upscaling, and denoiser GPU paths on non-Windows — require per-backend compute shader ports.
- A CI test harness that actively routes RT output through
MetalGoldenImageCaptureneeds a stable reference-image policy.
-
Original entry date: 2026-04-18 (consolidated from 11 incremental sessions in
.claude/knowledge/mac-compatibility-analysis.md, dated 2026-04-17 through 2026-04-18). - Verified against codebase 2026-06-08.
Updates / status changes since the original:
-
Metal backend — confirmed implemented:
MetalDevice.mmpresent (~70 KB). The original's earliest "critical gap" entry called it header-only; later sessions delivered it. Status: Resolved. -
Metal companion TUs —
MetalRayTracing,MetalTextureReadback, andMetalGoldenImageCapture(.h + .mm) all present. Status: Implemented. -
Input —
InputManager.cppnow has macOS/SDL branches (originally Win32-only). Status: Resolved. -
CMake presets — current set is
macos-debug,macos-release,macos-metal,macos-moltenvk, matching the documented end-state. - OpenGL 4.1 cap — still an open constraint (fallback only).
- Hardware-RT remaining items (deeper kernels, per-draw constants, GPU compute ports on non-Windows, golden-image CI harness) — still Open.
- The narrative was consolidated from 11 dated session logs into the current-state form; no factual claims were invented.
Published from 2b03dc797148. Edit the canonical source in wiki/.
- Documentation
- Docs route
- Wiki index
- Guides
- Tutorials
- Samples
- Examples
- API Reference
- API route
- Reference
- Build Guide
- Dependencies
- FAQ
- Changelog
- Roadmap
- Contributing
- Code of Conduct
- Home
- FAQ
- Getting Started
- Quick-Start Tutorial
- Making Your First Game
- Making Your First Multiplayer Game
- Artist Workflow Guide
- Editor Walkthrough
- Migration Guide
- How SparkEngine Works
- Architecture Overview
- Engine Architecture Flowchart
- Creating a Game Module
- Game Modules (catalog)
- Entity Component System
- Rendering and Graphics
- Physics
- Cloth Simulation
- Audio
- Input System
- Camera System
- Scripting with AngelScript
- Visual Scripting
- AI and Navigation
- Animation
- 2D Systems
- Networking
- Dedicated Server
- Multiplayer Quick Start
- Area Server Architecture
- Scene Management
- Large World Support
- Collaborative Editing
- Coroutine System
- Event System
- Event Response System
- Job System
- UI System
- UI Layout Extensions
- Localization
- Dialogue System
- Destruction System
- Replay System
- Achievement System
- Loading System
- Mod System
- Content Delivery
- Tween System
- Memory Integrity
- Gameplay Systems
- Terrain and Procedural Generation
- Save System
- Persistence System
- Day Night Cycle and Weather
- Cinematic Sequencer
- Runtime Prefabs
- SparkEditor
- Editor Tutorials
- SparkConsole
- SparkDaemon
- Shader Pipeline
- Asset Pipeline
- Asset Validation
- Asset Migration
- Game Packaging
- Online Services
- DataTable System
- Loot and Crafting System
- CSG System
- Font System
- Timer Manager
- Movie Render Pipeline
- HLOD and World Partition
- Remote Debug System
- Selection Manager
- Asset Dependency Graph
- Editor Automation
- File Watcher
- Project Templates
- System Requirements
- VR Support
- Mobile Platform
- Accessibility
- Platform Input
- Platform Certification
- Cross-Compilation: Wine Testing
- RHI Abstraction Layer
- D3D11 Backend
- D3D12 Backend
- Vulkan Backend
- OpenGL Backend
- Metal Backend
- DXR Raytracing
- Hybrid Ray Tracing
- Upscaling (DLSS/FSR)
- Render Graph
- Shader Graph
- GPU Particles
- GPU-Driven Rendering
- Volumetric Fog
- Volumetric Clouds
- Global Illumination
- Virtual Texturing
- Water Rendering
- Clustered Lighting
- Material System
- Post-Processing
- Shadow System
- Particle System
- Decal System
- Sky and Atmosphere
- Foliage System
- Mesh Shaders
- Neural Rendering
- Configuration Reference
- Performance Tips
- Benchmark Framework
- Threading Model
- Fuzz Policy and Parser Security
- Memory Safety
- Memory Management Patterns
- Build System and CMake Modules
- Profiler and Debugging
- Performance Profiling Guide
- Telemetry System
- Crash Reporting
- Golden Image Testing
- Utilities
- Testing
- Fuzz Policy and Parser Security
- Codebase Statistics
- Codebase Health
- Error Handling Patterns
- Hot Reload Overview
- Troubleshooting
- Contributing
- Workflow Patterns
- Build Optimizations
- CI Reproducible Builds
- GitHub API and PR Checks
- Git Rebase Conflicts
- Clang-Format
- Code Quality Violations
- AI Bloat Pattern
- MinGW + Wine Cross-Compilation
- Live Editor Testing
- Engine & Renderer Landscape
- DuetOS Portability Catalog
- Five-Engine Analysis
- Eleven-Engine Analysis
- ThorVG / Unity Graphics Analysis
- Advanced Techniques Catalog
- Third-Party Library Evaluation
- Engine Viability Evaluation
- Engine Feature Recommendations
- Project Recommendations
- Mac Compatibility Analysis
- Codebase Observations
- Codebase Bloat Audit
- Test Suite Audit
- Documentation Coverage Audit
- ThirdParty Dependencies Audit
- Load Test Baseline
- Gameplay Systems Status
- SparkGame Module Status
- Stub and Abandoned Features
- Memory Integrity System
- Memory Safety Evaluation
- Hardware Acceleration Systems
- Jolt Physics Integration
- GPU/CPU Separation Plan
- Daemon Services Architecture
- Reflection & Polymorphism Refactoring Plan
- SparkBuild In-Tree
- Wine No-JobSystem Breakthrough
- Wine Role and Fallback Tiers