summaryrefslogtreecommitdiff
path: root/src/gpu/headless_gpu.cc
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-09 19:34:46 +0100
committerskal <pascal.massimino@gmail.com>2026-02-09 19:34:46 +0100
commitf449fe7f78e059d455dfefcf4b09d763363f6344 (patch)
tree0a1e6ebfc42025e4e72200d3c34e2bf799a32aa8 /src/gpu/headless_gpu.cc
parentdd42eeef53df8ea36f436986f915f29986c094a3 (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/gpu/headless_gpu.cc')
-rw-r--r--src/gpu/headless_gpu.cc93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/gpu/headless_gpu.cc b/src/gpu/headless_gpu.cc
new file mode 100644
index 0000000..1a649d3
--- /dev/null
+++ b/src/gpu/headless_gpu.cc
@@ -0,0 +1,93 @@
+// Headless GPU implementation - functional stubs for testing
+// Workspace: demo (shared across all workspaces)
+
+#if defined(DEMO_HEADLESS)
+
+#include "gpu.h"
+#include "platform/stub_types.h"
+#include <stdio.h>
+
+static bool g_initialized = false;
+
+GpuBuffer gpu_create_buffer(WGPUDevice device, size_t size, uint32_t usage,
+ const void* data) {
+ (void)device;
+ (void)size;
+ (void)usage;
+ (void)data;
+ return {nullptr, 0};
+}
+
+RenderPass gpu_create_render_pass(WGPUDevice device, WGPUTextureFormat format,
+ const char* shader_code,
+ ResourceBinding* bindings, int num_bindings) {
+ (void)device;
+ (void)format;
+ (void)shader_code;
+ (void)bindings;
+ (void)num_bindings;
+ return {nullptr, nullptr, 0, 0};
+}
+
+ComputePass gpu_create_compute_pass(WGPUDevice device, const char* shader_code,
+ ResourceBinding* bindings,
+ int num_bindings) {
+ (void)device;
+ (void)shader_code;
+ (void)bindings;
+ (void)num_bindings;
+ return {nullptr, nullptr, 0, 0, 0};
+}
+
+void gpu_init(PlatformState* platform_state) {
+ (void)platform_state;
+ if (!g_initialized) {
+ printf("[headless] GPU initialized\n");
+ g_initialized = true;
+ }
+}
+
+void gpu_draw(float audio_peak, float aspect_ratio, float time, float beat) {
+ (void)audio_peak;
+ (void)aspect_ratio;
+ (void)time;
+ (void)beat;
+}
+
+void gpu_resize(int width, int height) {
+ (void)width;
+ (void)height;
+}
+
+void gpu_shutdown() {
+ if (g_initialized) {
+ printf("[headless] GPU shutdown\n");
+ g_initialized = false;
+ }
+}
+
+const GpuContext* gpu_get_context() {
+ static GpuContext ctx = {nullptr, nullptr, WGPUTextureFormat_BGRA8Unorm};
+ return &ctx;
+}
+
+MainSequence* gpu_get_main_sequence() {
+ return nullptr;
+}
+
+#if !defined(STRIP_ALL)
+void gpu_simulate_until(float time, float bpm) {
+ (void)time;
+ (void)bpm;
+}
+
+void gpu_add_custom_effect(Effect* effect, float start_time, float end_time,
+ int priority) {
+ (void)effect;
+ (void)start_time;
+ (void)end_time;
+ (void)priority;
+}
+#endif
+
+#endif // DEMO_HEADLESS