Getting Started
SafiEngine has zero manual dependency setup — all you need is CMake and a
C/C++ toolchain. Everything else is pulled in by CMake's FetchContent on the
first configure.
Prerequisites
- CMake ≥ 3.16
- A C11 and C++17 compiler. The engine itself is pure C, but a few fetched
dependencies (Jolt Physics, Dear ImGui) are C++:
- Windows — Visual Studio 2022 or newer with the "Desktop development with C++" workload (provides MSVC + the Windows SDK)
- macOS — Xcode command-line tools (
xcode-select --install) - Linux — GCC or Clang, plus the dev packages SDL needs (X11/Wayland)
- Git —
FetchContentuses it to clone the third-party sources - A GPU with Vulkan, Metal, or Direct3D 12 drivers — SDL picks the backend automatically (Metal on macOS, Vulkan or D3D12 on Windows/Linux)
The first cmake configure downloads every dependency, a sample glTF asset, and
a font into build/_deps/. After that, builds are fully offline and incremental.
Build
Run
Three runnable targets are built:
Shaders and the GPU backend
Shaders are authored once in HLSL under SafiEngine/engine/shaders/, then
compiled at build time to SPIR-V (Vulkan / D3D12) and transpiled to MSL
(Metal) — so the same source runs on every backend SDL selects.
SDL_GPU maps HLSL resources to fixed descriptor sets. In a fragment shader,
textures and samplers belong in space2, but uniform buffers must be in
space3 (see SDL_CreateGPUShader in SDL_gpu.h). Putting a fragment uniform
buffer in space2 collides with the texture bindings and renders garbage on
Vulkan — even though Metal's binding remap may hide it.
IDE / clangd
SafiEngine/cmake/ClangdSetup.cmake copies compile_commands.json into
SafiEngine/ after each build, so Zed, VS Code, Neovim, and CLion resolve every
engine header with no per-editor config.
compile_commands.json is only produced by the Makefile and Ninja
generators. Under the Visual Studio generator (the Windows default) it is not
generated, so the copy is skipped — configure with -G Ninja on Windows if you
want clangd to work.