diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-09 19:34:46 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-09 19:34:46 +0100 |
| commit | f449fe7f78e059d455dfefcf4b09d763363f6344 (patch) | |
| tree | 0a1e6ebfc42025e4e72200d3c34e2bf799a32aa8 /src/main.cc | |
| parent | dd42eeef53df8ea36f436986f915f29986c094a3 (diff) | |
feat: Add headless mode for testing without GPU
Implements DEMO_HEADLESS build option for fast iteration cycles:
- Functional GPU/platform stubs (not pure no-ops like STRIP_EXTERNAL_LIBS)
- Audio and timeline systems work normally
- No rendering overhead
- Useful for CI, audio development, timeline validation
Files added:
- doc/HEADLESS_MODE.md - Documentation
- src/gpu/headless_gpu.cc - Validated GPU stubs
- src/platform/headless_platform.cc - Time simulation (60Hz)
- scripts/test_headless.sh - End-to-end test script
Usage:
cmake -B build_headless -DDEMO_HEADLESS=ON
cmake --build build_headless -j4
./build_headless/demo64k --headless --duration 30
Progress printed every 5s. Compatible with --dump_wav mode.
handoff(Claude): Task #76 follow-up - headless mode complete
Diffstat (limited to 'src/main.cc')
| -rw-r--r-- | src/main.cc | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/src/main.cc b/src/main.cc index b4091e7..58ea124 100644 --- a/src/main.cc +++ b/src/main.cc @@ -32,6 +32,8 @@ int main(int argc, char** argv) { int height = 720; bool dump_wav = false; bool tempo_test_enabled = false; + bool headless_mode = false; + float headless_duration = 30.0f; const char* wav_output_file = "audio_dump.wav"; bool hot_reload_enabled = false; @@ -59,6 +61,11 @@ int main(int argc, char** argv) { } } else if (strcmp(argv[i], "--tempo") == 0) { tempo_test_enabled = true; + } else if (strcmp(argv[i], "--headless") == 0) { + headless_mode = true; + } else if (strcmp(argv[i], "--duration") == 0 && i + 1 < argc) { + headless_duration = atof(argv[i + 1]); + ++i; } else if (strcmp(argv[i], "--hot-reload") == 0) { hot_reload_enabled = true; printf("Hot-reload enabled (watching config files)\n"); @@ -74,7 +81,9 @@ int main(int argc, char** argv) { gpu_init(&platform_state); // Load timeline data (visual effects layering) +#if !defined(DEMO_HEADLESS) LoadTimeline(*gpu_get_main_sequence(), *gpu_get_context()); +#endif #if !defined(STRIP_ALL) // Set WAV dump backend if requested @@ -182,6 +191,34 @@ int main(int argc, char** argv) { #endif #if !defined(STRIP_ALL) + // In headless mode, run simulation without rendering + if (headless_mode) { + printf("Running headless simulation (%.1fs)...\n", headless_duration); + + const float update_dt = 1.0f / 60.0f; + double physical_time = 0.0; + while (physical_time < headless_duration) { + fill_audio_buffer(update_dt, physical_time); + gpu_simulate_until(g_music_time); + physical_time += update_dt; + + if ((int)physical_time % 5 == 0 && + physical_time - update_dt < (int)physical_time) { + printf(" Progress: %.1fs / %.1fs (music: %.1fs)\r", + physical_time, headless_duration, g_music_time); + fflush(stdout); + } + } + + printf("\nHeadless simulation complete: %.2fs\n", physical_time); + + g_audio_engine.shutdown(); + audio_shutdown(); + gpu_shutdown(); + platform_shutdown(&platform_state); + return 0; + } + // In WAV dump mode, run headless simulation and write audio to file if (dump_wav) { printf("Running WAV dump simulation...\n"); |
