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)
  • GitFetchContent uses 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)
First configure needs the network

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

cd SafiEngine
cmake -S . -B build
cmake --build build -j

Run

# macOS / Linux — single-config generators put binaries here
./build/examples/gltf_viewer/gltf_viewer

# Windows — Visual Studio is multi-config, so binaries land under Debug/
.\build\examples\gltf_viewer\Debug\gltf_viewer.exe

Three runnable targets are built:

TargetWhat it is
gltf_viewerThe demo scene — a loaded glTF model + procedural shapes
safi_editorThe editor Hub (see the Editor guide)
safi_runtimeThe headless-ish runtime that plays a project

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.

HLSL register-space convention

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.