raylib performance — backend comparison
rlvk (moltenvk) vs rlvk (moltenvk threaded) | GPU Apple M5 (24576 MB) | Driver MoltenVK 1.4.2 | OS macOS 26.5.1 | 3 runs × 10000 ms full speed
Green = best backend for that example/metric, red = worst. Frame time & FPS are the representative run; software (rlsw) has no GPU so its VRAM is ~0. Shader-heavy examples may not execute custom shaders on the software backend.
° = at that backend's floor (median within 15% of its own bench_idle median): the scene finishes its real work faster than one present/loop turnaround, so the number measures presentation pacing or loop overhead, not rendering cost, and cross-backend ratios there compare present plumbing. On macOS, Metal-backed Vulkan presents pace on drawable acquire (~1.6-1.8 ms) while GL's IOSurface flush has no floor - only rows without ° compare backend rendering cost.
Read this before comparing FPS on macOS. Uncapped FPS on light scenes here measures presentation, not rendering. Apple GL presents by flushing an IOSurface — no per-frame handshake, essentially free — while Vulkan on macOS (MoltenVK or KosmicKrisp) can only present through Metal, which must acquire a CAMetalDrawable from CoreAnimation each frame, paced at ~1.6–1.8 ms on a composited window no matter how little the frame draws. Measured on shapes_basic_shapes, uncapped: frame interval avg 1.95 ms, of which 1.76 ms (90%) is "Retrieve a CAMetalDrawable" (MoltenVK's own performance tracking; the drawing itself costs ~0.12 ms and the GPU is nearly idle). Every native Metal app pays the same pacing; no driver knob removes it (KosmicKrisp's is lowered from ~3.3 to ~1.6 ms by MESA_VK_WSI_PRESENT_MODE=mailbox, MoltenVK's config surface is exhausted). Cells marked ° sit at that backend's floor: their cross-backend ratios compare macOS present plumbing. Rows above the floor compare real rendering — there the Vulkan backend leads (e.g. 8000 draw calls: 120 fps GL vs 581 fps rlvk). Under vsync all backends lock to the display rate and the floor is invisible.
speedup = rlvk (moltenvk threaded) relative to rlvk (moltenvk), per metric direction (>1x favors rlvk (moltenvk threaded)); ° on a ratio means at least one side sits at its floor, so it compares present plumbing.
Frames per second (higher is better)
Sustained FPS at full speed (uncapped).| Example | rlvk (moltenvk) | rlvk (moltenvk threaded) | rlvk (moltenvk threaded) speedup |
|---|
| shapes_basic_shapes | 516° | 8310° | 16.11x° |
| textures_tiled_drawing | 472° | 8418° | 17.83x° |
| textures_particles_blending | 532° | 7990° | 15.03x° |
| shapes_starfield_effect | 529° | 8236° | 15.58x° |
| models_loading | 289 | 7887° | 27.33x° |
| models_heightmap_rendering | 559° | 7630° | 13.66x° |
| models_skybox_rendering | 331 | 8253° | 24.91x° |
| models_waving_cubes | 544° | 1294 | 2.38x° |
| models_first_person_maze | 309 | 8192° | 26.49x° |
| core_3d_camera_free | 353 | 6687° | 18.95x° |
| shaders_basic_lighting | 512° | 6934° | 13.53x° |
| shaders_basic_pbr | 282 | 6115 | 21.72x |
| shaders_mandelbrot_set | 412° | 4357 | 10.59x° |
| shaders_raymarching_rendering | 156 | 262 | 1.68x |
| performance_stress_test | 195 | 178 | 0.91x |
| performance_stress_test_direct | 3 | 3 | 0.95x |
| bench_idle | 415° | 8363° | 20.14x° |
| bench_drawcalls | 474° | 1693 | 3.57x° |
| bench_instanced | 362 | 6800 | 18.81x |
Median frame time, ms (lower is better)
Median per-frame CPU wall time.| Example | rlvk (moltenvk) | rlvk (moltenvk threaded) | rlvk (moltenvk threaded) speedup |
|---|
| shapes_basic_shapes | 1.601° | 0.104° | 15.39x° |
| textures_tiled_drawing | 1.616° | 0.105° | 15.39x° |
| textures_particles_blending | 1.603° | 0.114° | 14.06x° |
| shapes_starfield_effect | 1.603° | 0.105° | 15.27x° |
| models_loading | 3.369 | 0.110° | 30.63x° |
| models_heightmap_rendering | 1.684° | 0.118° | 14.27x° |
| models_skybox_rendering | 3.044 | 0.105° | 28.99x° |
| models_waving_cubes | 1.657° | 0.767 | 2.16x° |
| models_first_person_maze | 3.291 | 0.106° | 31.05x° |
| core_3d_camera_free | 2.931 | 0.107° | 27.39x° |
| shaders_basic_lighting | 1.606° | 0.113° | 14.21x° |
| shaders_basic_pbr | 3.405 | 0.171 | 19.91x |
| shaders_mandelbrot_set | 1.888° | 0.226 | 8.35x° |
| shaders_raymarching_rendering | 3.656 | 3.738 | 0.98x |
| performance_stress_test | 5.101 | 5.528 | 0.92x |
| performance_stress_test_direct | 325.523 | 340.785 | 0.96x |
| bench_idle | 1.840° | 0.109° | 16.88x° |
| bench_drawcalls | 1.835° | 0.585 | 3.14x° |
| bench_instanced | 2.472 | 0.164 | 15.07x |
Average frame time, ms (lower is better)
Mean per-frame wall time.| Example | rlvk (moltenvk) | rlvk (moltenvk threaded) | rlvk (moltenvk threaded) speedup |
|---|
| shapes_basic_shapes | 1.939° | 0.120° | 16.11x° |
| textures_tiled_drawing | 2.119° | 0.119° | 17.83x° |
| textures_particles_blending | 1.881° | 0.125° | 15.03x° |
| shapes_starfield_effect | 1.892° | 0.121° | 15.58x° |
| models_loading | 3.464 | 0.127° | 27.33x° |
| models_heightmap_rendering | 1.790° | 0.131° | 13.66x° |
| models_skybox_rendering | 3.018 | 0.121° | 24.91x° |
| models_waving_cubes | 1.837° | 0.773 | 2.38x° |
| models_first_person_maze | 3.233 | 0.122° | 26.49x° |
| core_3d_camera_free | 2.833 | 0.150° | 18.95x° |
| shaders_basic_lighting | 1.951° | 0.144° | 13.53x° |
| shaders_basic_pbr | 3.552 | 0.164 | 21.72x |
| shaders_mandelbrot_set | 2.430° | 0.230 | 10.59x° |
| shaders_raymarching_rendering | 6.413 | 3.817 | 1.68x |
| performance_stress_test | 5.123 | 5.629 | 0.91x |
| performance_stress_test_direct | 329.243 | 347.228 | 0.95x |
| bench_idle | 2.408° | 0.120° | 20.14x° |
| bench_drawcalls | 2.111° | 0.591 | 3.57x° |
| bench_instanced | 2.766 | 0.147 | 18.81x |
CPU utilization, %
Average process CPU as percent of the whole machine.| Example | rlvk (moltenvk) | rlvk (moltenvk threaded) | rlvk (moltenvk threaded) speedup |
|---|
| shapes_basic_shapes | 3.9 | 9.9 | 0.39x |
| textures_tiled_drawing | 3.5 | 10.3 | 0.35x |
| textures_particles_blending | 4.2 | 10.0 | 0.42x |
| shapes_starfield_effect | 4.1 | 10.0 | 0.41x |
| models_loading | 1.9 | 9.4 | 0.20x |
| models_heightmap_rendering | 4.4 | 9.1 | 0.48x |
| models_skybox_rendering | 2.1 | 9.5 | 0.22x |
| models_waving_cubes | 7.6 | 11.8 | 0.64x |
| models_first_person_maze | 2.0 | 9.6 | 0.21x |
| core_3d_camera_free | 2.3 | 9.0 | 0.25x |
| shaders_basic_lighting | 4.3 | 9.0 | 0.47x |
| shaders_basic_pbr | 2.1 | 8.2 | 0.25x |
| shaders_mandelbrot_set | 3.2 | 6.9 | 0.46x |
| shaders_raymarching_rendering | 1.3 | 0.8 | 1.60x |
| performance_stress_test | 10.3 | 10.5 | 0.98x |
| performance_stress_test_direct | 0.0 | 0.0 | 0.39x |
| bench_idle | 2.9 | 9.8 | 0.30x |
| bench_drawcalls | 7.7 | 9.5 | 0.81x |
| bench_instanced | 3.1 | 11.2 | 0.28x |
RAM, MB
Average working-set memory.| Example | rlvk (moltenvk) | rlvk (moltenvk threaded) | rlvk (moltenvk threaded) speedup |
|---|
| shapes_basic_shapes | 85.4 | 87.7 | 0.97x |
| textures_tiled_drawing | 85.7 | 88.3 | 0.97x |
| textures_particles_blending | 85.5 | 87.8 | 0.97x |
| shapes_starfield_effect | 85.3 | 87.7 | 0.97x |
| models_loading | 101.2 | 103.0 | 0.98x |
| models_heightmap_rendering | 88.7 | 90.9 | 0.98x |
| models_skybox_rendering | 161.7 | 164.2 | 0.98x |
| models_waving_cubes | 92.8 | 93.9 | 0.99x |
| models_first_person_maze | 86.3 | 88.3 | 0.98x |
| core_3d_camera_free | 85.2 | 87.3 | 0.98x |
| shaders_basic_lighting | 102.4 | 104.6 | 0.98x |
| shaders_basic_pbr | 140.7 | 141.8 | 0.99x |
| shaders_mandelbrot_set | 103.6 | 105.4 | 0.98x |
| shaders_raymarching_rendering | 118.9 | 120.3 | 0.99x |
| performance_stress_test | 152.8 | 153.1 | 1.00x |
| performance_stress_test_direct | 104.0 | 105.9 | 0.98x |
| bench_idle | 84.9 | 87.5 | 0.97x |
| bench_drawcalls | 86.5 | 87.9 | 0.98x |
| bench_instanced | 103.6 | 105.7 | 0.98x |
GPU VRAM, MB
Average per-process video memory.| Example | rlvk (moltenvk) | rlvk (moltenvk threaded) | rlvk (moltenvk threaded) speedup |
|---|
| shapes_basic_shapes | 0.0 | 0.0 | — |
| textures_tiled_drawing | 0.0 | 0.0 | — |
| textures_particles_blending | 0.0 | 0.0 | — |
| shapes_starfield_effect | 0.0 | 0.0 | — |
| models_loading | 0.0 | 0.0 | — |
| models_heightmap_rendering | 0.0 | 0.0 | — |
| models_skybox_rendering | 0.0 | 0.0 | — |
| models_waving_cubes | 0.0 | 0.0 | — |
| models_first_person_maze | 0.0 | 0.0 | — |
| core_3d_camera_free | 0.0 | 0.0 | — |
| shaders_basic_lighting | 0.0 | 0.0 | — |
| shaders_basic_pbr | 0.0 | 0.0 | — |
| shaders_mandelbrot_set | 0.0 | 0.0 | — |
| shaders_raymarching_rendering | 0.0 | 0.0 | — |
| performance_stress_test | 0.0 | 0.0 | — |
| performance_stress_test_direct | 0.0 | 0.0 | — |
| bench_idle | 0.0 | 0.0 | — |
| bench_drawcalls | 0.0 | 0.0 | — |
| bench_instanced | 0.0 | 0.0 | — |