raylib performance — backend comparison
rlvk (moltenvk) vs rlvk (kosmickrisp) vs rlgl | 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.
Frames per second (higher is better)
Sustained FPS at full speed (uncapped).| Example | rlvk (moltenvk) | rlvk (kosmickrisp) | rlgl |
|---|
| shapes_basic_shapes | 516° | 598° | 8151° |
| textures_tiled_drawing | 472° | 572° | 8043° |
| textures_particles_blending | 532° | 599° | 7572° |
| shapes_starfield_effect | 529° | 599° | 7833° |
| models_loading | 289 | 565° | 2416 |
| models_heightmap_rendering | 559° | 466° | 2240 |
| models_skybox_rendering | 331 | 599° | 2485 |
| models_waving_cubes | 544° | 599° | 384 |
| models_first_person_maze | 309 | 564° | 8299° |
| core_3d_camera_free | 353 | 564° | 2440 |
| shaders_basic_lighting | 512° | 569° | 4151 |
| shaders_basic_pbr | 282 | 366 | 3915 |
| shaders_mandelbrot_set | 412° | 535° | 1146 |
| shaders_raymarching_rendering | 156 | 250 | 311 |
| performance_stress_test | 195 | 146 | 81 |
| performance_stress_test_direct | 3 | 4 | 4 |
| bench_idle | 415° | 570° | 6256° |
| bench_drawcalls | 474° | 552° | 120 |
| bench_instanced | 362 | 496° | 691 |
Median frame time, ms (lower is better)
Median per-frame CPU wall time.| Example | rlvk (moltenvk) | rlvk (kosmickrisp) | rlgl |
|---|
| shapes_basic_shapes | 1.601° | 1.597° | 0.117° |
| textures_tiled_drawing | 1.616° | 1.599° | 0.118° |
| textures_particles_blending | 1.603° | 1.597° | 0.124° |
| shapes_starfield_effect | 1.603° | 1.597° | 0.122° |
| models_loading | 3.369 | 1.598° | 0.386 |
| models_heightmap_rendering | 1.684° | 1.615° | 0.406 |
| models_skybox_rendering | 3.044 | 1.597° | 0.374 |
| models_waving_cubes | 1.657° | 1.597° | 2.485 |
| models_first_person_maze | 3.291 | 1.599° | 0.111° |
| core_3d_camera_free | 2.931 | 1.599° | 0.381 |
| shaders_basic_lighting | 1.606° | 1.598° | 0.229 |
| shaders_basic_pbr | 3.405 | 2.668 | 0.245 |
| shaders_mandelbrot_set | 1.888° | 1.604° | 0.826 |
| shaders_raymarching_rendering | 3.656 | 3.784 | 3.421 |
| performance_stress_test | 5.101 | 6.874 | 12.083 |
| performance_stress_test_direct | 325.523 | 236.272 | 242.120 |
| bench_idle | 1.840° | 1.612° | 0.130° |
| bench_drawcalls | 1.835° | 1.635° | 7.894 |
| bench_instanced | 2.472 | 1.814° | 0.990 |
Average frame time, ms (lower is better)
Mean per-frame wall time.| Example | rlvk (moltenvk) | rlvk (kosmickrisp) | rlgl |
|---|
| shapes_basic_shapes | 1.939° | 1.672° | 0.123° |
| textures_tiled_drawing | 2.119° | 1.749° | 0.124° |
| textures_particles_blending | 1.881° | 1.670° | 0.132° |
| shapes_starfield_effect | 1.892° | 1.670° | 0.128° |
| models_loading | 3.464 | 1.771° | 0.414 |
| models_heightmap_rendering | 1.790° | 2.147° | 0.446 |
| models_skybox_rendering | 3.018 | 1.669° | 0.402 |
| models_waving_cubes | 1.837° | 1.669° | 2.601 |
| models_first_person_maze | 3.233 | 1.775° | 0.120° |
| core_3d_camera_free | 2.833 | 1.772° | 0.410 |
| shaders_basic_lighting | 1.951° | 1.757° | 0.241 |
| shaders_basic_pbr | 3.552 | 2.733 | 0.255 |
| shaders_mandelbrot_set | 2.430° | 1.870° | 0.873 |
| shaders_raymarching_rendering | 6.413 | 3.996 | 3.212 |
| performance_stress_test | 5.123 | 6.867 | 12.412 |
| performance_stress_test_direct | 329.243 | 236.202 | 241.852 |
| bench_idle | 2.408° | 1.754° | 0.160° |
| bench_drawcalls | 2.111° | 1.811° | 8.354 |
| bench_instanced | 2.766 | 2.017° | 1.448 |
CPU utilization, %
Average process CPU as percent of the whole machine.| Example | rlvk (moltenvk) | rlvk (kosmickrisp) | rlgl |
|---|
| shapes_basic_shapes | 3.9 | 3.2 | 12.9 |
| textures_tiled_drawing | 3.5 | 3.2 | 12.9 |
| textures_particles_blending | 4.2 | 3.2 | 12.0 |
| shapes_starfield_effect | 4.1 | 3.2 | 12.9 |
| models_loading | 1.9 | 3.1 | 5.4 |
| models_heightmap_rendering | 4.4 | 2.9 | 4.9 |
| models_skybox_rendering | 2.1 | 3.1 | 5.5 |
| models_waving_cubes | 7.6 | 9.0 | 7.1 |
| models_first_person_maze | 2.0 | 3.1 | 12.5 |
| core_3d_camera_free | 2.3 | 3.1 | 5.5 |
| shaders_basic_lighting | 4.3 | 3.9 | 12.1 |
| shaders_basic_pbr | 2.1 | 3.3 | 12.4 |
| shaders_mandelbrot_set | 3.2 | 4.1 | 3.8 |
| shaders_raymarching_rendering | 1.3 | 0.5 | 1.0 |
| performance_stress_test | 10.3 | 10.4 | 9.8 |
| performance_stress_test_direct | 0.0 | 0.0 | 0.0 |
| bench_idle | 2.9 | 4.4 | 9.1 |
| bench_drawcalls | 7.7 | 8.2 | 9.9 |
| bench_instanced | 3.1 | 3.9 | 2.4 |
RAM, MB
Average working-set memory.| Example | rlvk (moltenvk) | rlvk (kosmickrisp) | rlgl |
|---|
| shapes_basic_shapes | 85.4 | 93.4 | 87.0 |
| textures_tiled_drawing | 85.7 | 93.6 | 87.3 |
| textures_particles_blending | 85.5 | 93.5 | 87.2 |
| shapes_starfield_effect | 85.3 | 93.4 | 86.9 |
| models_loading | 101.2 | 108.4 | 103.1 |
| models_heightmap_rendering | 88.7 | 95.7 | 92.6 |
| models_skybox_rendering | 161.7 | 169.9 | 147.6 |
| models_waving_cubes | 92.8 | 100.9 | 87.8 |
| models_first_person_maze | 86.3 | 94.0 | 88.5 |
| core_3d_camera_free | 85.2 | 93.2 | 86.2 |
| shaders_basic_lighting | 102.4 | 111.6 | 97.2 |
| shaders_basic_pbr | 140.7 | 148.4 | 129.5 |
| shaders_mandelbrot_set | 103.6 | 111.5 | 86.1 |
| shaders_raymarching_rendering | 118.9 | 126.3 | 86.4 |
| performance_stress_test | 152.8 | 199.4 | 122.8 |
| performance_stress_test_direct | 104.0 | 111.1 | 86.4 |
| bench_idle | 84.9 | 93.1 | 86.5 |
| bench_drawcalls | 86.5 | 94.7 | 93.0 |
| bench_instanced | 103.6 | 111.6 | 87.3 |
GPU VRAM, MB
Average per-process video memory.| Example | rlvk (moltenvk) | rlvk (kosmickrisp) | rlgl |
|---|
| shapes_basic_shapes | 0.0 | 0.0 | 0.0 |
| textures_tiled_drawing | 0.0 | 0.0 | 0.0 |
| textures_particles_blending | 0.0 | 0.0 | 0.0 |
| shapes_starfield_effect | 0.0 | 0.0 | 0.0 |
| models_loading | 0.0 | 0.0 | 0.0 |
| models_heightmap_rendering | 0.0 | 0.0 | 0.0 |
| models_skybox_rendering | 0.0 | 0.0 | 0.0 |
| models_waving_cubes | 0.0 | 0.0 | 0.0 |
| models_first_person_maze | 0.0 | 0.0 | 0.0 |
| core_3d_camera_free | 0.0 | 0.0 | 0.0 |
| shaders_basic_lighting | 0.0 | 0.0 | 0.0 |
| shaders_basic_pbr | 0.0 | 0.0 | 0.0 |
| shaders_mandelbrot_set | 0.0 | 0.0 | 0.0 |
| shaders_raymarching_rendering | 0.0 | 0.0 | 0.0 |
| performance_stress_test | 0.0 | 0.0 | 0.0 |
| performance_stress_test_direct | 0.0 | 0.0 | 0.0 |
| bench_idle | 0.0 | 0.0 | 0.0 |
| bench_drawcalls | 0.0 | 0.0 | 0.0 |
| bench_instanced | 0.0 | 0.0 | 0.0 |