summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-01-31 17:23:13 +0100
committerskal <pascal.massimino@gmail.com>2026-01-31 17:23:13 +0100
commit32d26371627638570b74d678ab73deb7b87af8e4 (patch)
tree3097b3678086ddaed7930a02e5c88464f1c7d03e
parent7ec28a3f1d417cd5b5adead895a25e42035ef037 (diff)
fix: Cross-compilation and style compliance
Fixes seq_compiler build for Windows cross-compilation. Moves common WebGPU compatibility shims to gpu.h. Applies project-wide coding style via clang-format. Verified on both macOS (native) and Windows (cross-compile).
-rw-r--r--CMakeLists.txt13
-rw-r--r--demo_all.tgzbin0 -> 258457607 bytes
-rwxr-xr-xscripts/build_win.sh14
-rw-r--r--src/audio/audio.cc3
-rw-r--r--src/gpu/demo_effects.cc268
-rw-r--r--src/gpu/effect.cc42
-rw-r--r--src/gpu/effect.h21
-rw-r--r--src/gpu/gpu.cc16
-rw-r--r--src/gpu/gpu.h25
-rw-r--r--src/main.cc22
-rw-r--r--tools/seq_compiler.cc17
11 files changed, 302 insertions, 139 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3812fb7..bf8785d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -121,7 +121,14 @@ else()
endif()
# Sequence Compiler Tool
-add_executable(seq_compiler tools/seq_compiler.cc)
+if (DEFINED SEQ_COMPILER_PATH)
+ set(SEQ_COMPILER_CMD ${SEQ_COMPILER_PATH})
+ set(SEQ_COMPILER_DEPENDS ${SEQ_COMPILER_PATH})
+else()
+ add_executable(seq_compiler tools/seq_compiler.cc)
+ set(SEQ_COMPILER_CMD $<TARGET_FILE:seq_compiler>)
+ set(SEQ_COMPILER_DEPENDS seq_compiler)
+endif()
# Configure Timeline Generation
set(DEMO_SEQ_PATH ${CMAKE_CURRENT_SOURCE_DIR}/assets/demo.seq)
@@ -130,8 +137,8 @@ set(GENERATED_TIMELINE_CC ${CMAKE_CURRENT_BINARY_DIR}/src/timeline.cc)
add_custom_command(
OUTPUT ${GENERATED_TIMELINE_CC}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/src
- COMMAND $<TARGET_FILE:seq_compiler> ${DEMO_SEQ_PATH} ${GENERATED_TIMELINE_CC}
- DEPENDS seq_compiler ${DEMO_SEQ_PATH}
+ COMMAND ${SEQ_COMPILER_CMD} ${DEMO_SEQ_PATH} ${GENERATED_TIMELINE_CC}
+ DEPENDS ${SEQ_COMPILER_DEPENDS} ${DEMO_SEQ_PATH}
COMMENT "Compiling demo sequence..."
)
diff --git a/demo_all.tgz b/demo_all.tgz
new file mode 100644
index 0000000..7ec524d
--- /dev/null
+++ b/demo_all.tgz
Binary files differ
diff --git a/scripts/build_win.sh b/scripts/build_win.sh
index db95416..d61f308 100755
--- a/scripts/build_win.sh
+++ b/scripts/build_win.sh
@@ -4,16 +4,18 @@ set -e
# 1. Build native tools (asset_packer)
echo "Building native tools..."
cmake -S . -B build_native -DDEMO_BUILD_TOOLS=OFF -DDEMO_BUILD_TESTS=OFF
-cmake --build build_native --target asset_packer
+cmake --build build_native --target asset_packer seq_compiler
+
+ASSET_PACKER_PATH=$(pwd)/build_native/asset_packer
+SEQ_COMPILER_PATH=$(pwd)/build_native/seq_compiler
-# 2. Cross-compile for Windows
echo "Cross-compiling for Windows..."
cmake -S . -B build_win \
-DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-MinGW-w64.cmake \
- -DCMAKE_BUILD_TYPE=Release \
- -DASSET_PACKER_PATH=$(pwd)/build_native/asset_packer \
- -DDEMO_BUILD_TOOLS=OFF \
- -DDEMO_BUILD_TESTS=OFF
+ -DDEMO_CROSS_COMPILE_WIN32=ON \
+ -DDEMO_STRIP_ALL=ON \
+ -DASSET_PACKER_PATH=$ASSET_PACKER_PATH \
+ -DSEQ_COMPILER_PATH=$SEQ_COMPILER_PATH
cmake --build build_win
diff --git a/src/audio/audio.cc b/src/audio/audio.cc
index a1a6f7b..4341712 100644
--- a/src/audio/audio.cc
+++ b/src/audio/audio.cc
@@ -56,7 +56,8 @@ void audio_render_silent(float duration_sec) {
float buffer[chunk_size * 2]; // Stereo
while (total_frames > 0) {
- int frames_to_render = (total_frames > chunk_size) ? chunk_size : total_frames;
+ int frames_to_render =
+ (total_frames > chunk_size) ? chunk_size : total_frames;
synth_render(buffer, frames_to_render);
total_frames -= frames_to_render;
}
diff --git a/src/gpu/demo_effects.cc b/src/gpu/demo_effects.cc
index 5d7419d..71f1284 100644
--- a/src/gpu/demo_effects.cc
+++ b/src/gpu/demo_effects.cc
@@ -243,14 +243,21 @@ struct Uniforms { time: f32, beat: f32, intensity: f32, aspect_ratio: f32, };
})";
// --- HeptagonEffect ---
-HeptagonEffect::HeptagonEffect(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format) : queue_(queue) {
- uniforms_ = gpu_create_buffer(device, sizeof(float) * 4, WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
+HeptagonEffect::HeptagonEffect(WGPUDevice device, WGPUQueue queue,
+ WGPUTextureFormat format)
+ : queue_(queue) {
+ uniforms_ =
+ gpu_create_buffer(device, sizeof(float) * 4,
+ WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
ResourceBinding bindings[] = {{uniforms_, WGPUBufferBindingType_Uniform}};
pass_ = gpu_create_render_pass(device, format, main_shader_wgsl, bindings, 1);
pass_.vertex_count = 21;
}
-void HeptagonEffect::render(WGPURenderPassEncoder pass, float t, float b, float i, float a) {
- struct { float p, a, t, d; } u = {i, a, t, 0.0f};
+void HeptagonEffect::render(WGPURenderPassEncoder pass, float t, float b,
+ float i, float a) {
+ struct {
+ float p, a, t, d;
+ } u = {i, a, t, 0.0f};
wgpuQueueWriteBuffer(queue_, uniforms_.buffer, 0, &u, sizeof(u));
wgpuRenderPassEncoderSetPipeline(pass, pass_.pipeline);
wgpuRenderPassEncoderSetBindGroup(pass, 0, pass_.bind_group, 0, nullptr);
@@ -258,54 +265,91 @@ void HeptagonEffect::render(WGPURenderPassEncoder pass, float t, float b, float
}
// --- ParticlesEffect ---
-ParticlesEffect::ParticlesEffect(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format) : queue_(queue) {
- uniforms_ = gpu_create_buffer(device, sizeof(float) * 4, WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
+ParticlesEffect::ParticlesEffect(WGPUDevice device, WGPUQueue queue,
+ WGPUTextureFormat format)
+ : queue_(queue) {
+ uniforms_ =
+ gpu_create_buffer(device, sizeof(float) * 4,
+ WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
std::vector<Particle> init_p(NUM_PARTICLES);
- particles_buffer_ = gpu_create_buffer(device, sizeof(Particle) * NUM_PARTICLES, WGPUBufferUsage_Storage | WGPUBufferUsage_Vertex, init_p.data());
- ResourceBinding cb[] = {{particles_buffer_, WGPUBufferBindingType_Storage}, {uniforms_, WGPUBufferBindingType_Uniform}};
+ particles_buffer_ = gpu_create_buffer(
+ device, sizeof(Particle) * NUM_PARTICLES,
+ WGPUBufferUsage_Storage | WGPUBufferUsage_Vertex, init_p.data());
+ ResourceBinding cb[] = {{particles_buffer_, WGPUBufferBindingType_Storage},
+ {uniforms_, WGPUBufferBindingType_Uniform}};
compute_pass_ = gpu_create_compute_pass(device, particle_compute_wgsl, cb, 2);
compute_pass_.workgroup_size_x = (NUM_PARTICLES + 63) / 64;
- ResourceBinding rb[] = {{particles_buffer_, WGPUBufferBindingType_ReadOnlyStorage}, {uniforms_, WGPUBufferBindingType_Uniform}};
- render_pass_ = gpu_create_render_pass(device, format, particle_render_wgsl, rb, 2);
- render_pass_.vertex_count = 6; render_pass_.instance_count = NUM_PARTICLES;
+ ResourceBinding rb[] = {
+ {particles_buffer_, WGPUBufferBindingType_ReadOnlyStorage},
+ {uniforms_, WGPUBufferBindingType_Uniform}};
+ render_pass_ =
+ gpu_create_render_pass(device, format, particle_render_wgsl, rb, 2);
+ render_pass_.vertex_count = 6;
+ render_pass_.instance_count = NUM_PARTICLES;
}
-void ParticlesEffect::compute(WGPUCommandEncoder e, float t, float b, float i, float a) {
- struct { float p, a, t, d; } u = {i, a, t, 0.0f};
+void ParticlesEffect::compute(WGPUCommandEncoder e, float t, float b, float i,
+ float a) {
+ struct {
+ float p, a, t, d;
+ } u = {i, a, t, 0.0f};
wgpuQueueWriteBuffer(queue_, uniforms_.buffer, 0, &u, sizeof(u));
WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(e, nullptr);
wgpuComputePassEncoderSetPipeline(pass, compute_pass_.pipeline);
- wgpuComputePassEncoderSetBindGroup(pass, 0, compute_pass_.bind_group, 0, nullptr);
- wgpuComputePassEncoderDispatchWorkgroups(pass, compute_pass_.workgroup_size_x, 1, 1);
+ wgpuComputePassEncoderSetBindGroup(pass, 0, compute_pass_.bind_group, 0,
+ nullptr);
+ wgpuComputePassEncoderDispatchWorkgroups(pass, compute_pass_.workgroup_size_x,
+ 1, 1);
wgpuComputePassEncoderEnd(pass);
}
-void ParticlesEffect::render(WGPURenderPassEncoder pass, float t, float b, float i, float a) {
+void ParticlesEffect::render(WGPURenderPassEncoder pass, float t, float b,
+ float i, float a) {
wgpuRenderPassEncoderSetPipeline(pass, render_pass_.pipeline);
- wgpuRenderPassEncoderSetBindGroup(pass, 0, render_pass_.bind_group, 0, nullptr);
- wgpuRenderPassEncoderDraw(pass, render_pass_.vertex_count, render_pass_.instance_count, 0, 0);
+ wgpuRenderPassEncoderSetBindGroup(pass, 0, render_pass_.bind_group, 0,
+ nullptr);
+ wgpuRenderPassEncoderDraw(pass, render_pass_.vertex_count,
+ render_pass_.instance_count, 0, 0);
}
// --- PassthroughEffect ---
-PassthroughEffect::PassthroughEffect(WGPUDevice device, WGPUTextureFormat format) : device_(device) {
- pipeline_ = create_post_process_pipeline(device, format, passthrough_shader_wgsl);
+PassthroughEffect::PassthroughEffect(WGPUDevice device,
+ WGPUTextureFormat format)
+ : device_(device) {
+ pipeline_ =
+ create_post_process_pipeline(device, format, passthrough_shader_wgsl);
}
void PassthroughEffect::update_bind_group(WGPUTextureView input_view) {
- if (bind_group_) wgpuBindGroupRelease(bind_group_);
+ if (bind_group_)
+ wgpuBindGroupRelease(bind_group_);
WGPUBindGroupLayout bgl = wgpuRenderPipelineGetBindGroupLayout(pipeline_, 0);
- WGPUSamplerDescriptor sd = {}; WGPUSampler sampler = wgpuDeviceCreateSampler(device_, &sd);
- WGPUBindGroupEntry bge[2] = {}; bge[0].binding = 0; bge[0].sampler = sampler; bge[1].binding = 1; bge[1].textureView = input_view;
- WGPUBindGroupDescriptor bgd = {.layout = bgl, .entryCount = 2, .entries = bge};
+ WGPUSamplerDescriptor sd = {};
+ WGPUSampler sampler = wgpuDeviceCreateSampler(device_, &sd);
+ WGPUBindGroupEntry bge[2] = {};
+ bge[0].binding = 0;
+ bge[0].sampler = sampler;
+ bge[1].binding = 1;
+ bge[1].textureView = input_view;
+ WGPUBindGroupDescriptor bgd = {
+ .layout = bgl, .entryCount = 2, .entries = bge};
bind_group_ = wgpuDeviceCreateBindGroup(device_, &bgd);
}
// --- MovingEllipseEffect ---
-MovingEllipseEffect::MovingEllipseEffect(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format) : queue_(queue) {
- uniforms_ = gpu_create_buffer(device, sizeof(float) * 4, WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
+MovingEllipseEffect::MovingEllipseEffect(WGPUDevice device, WGPUQueue queue,
+ WGPUTextureFormat format)
+ : queue_(queue) {
+ uniforms_ =
+ gpu_create_buffer(device, sizeof(float) * 4,
+ WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
ResourceBinding bindings[] = {{uniforms_, WGPUBufferBindingType_Uniform}};
- pass_ = gpu_create_render_pass(device, format, ellipse_shader_wgsl, bindings, 1);
+ pass_ =
+ gpu_create_render_pass(device, format, ellipse_shader_wgsl, bindings, 1);
pass_.vertex_count = 3;
}
-void MovingEllipseEffect::render(WGPURenderPassEncoder pass, float t, float b, float i, float a) {
- struct { float t, b, i, a; } u = {t, b, i, a};
+void MovingEllipseEffect::render(WGPURenderPassEncoder pass, float t, float b,
+ float i, float a) {
+ struct {
+ float t, b, i, a;
+ } u = {t, b, i, a};
wgpuQueueWriteBuffer(queue_, uniforms_.buffer, 0, &u, sizeof(u));
wgpuRenderPassEncoderSetPipeline(pass, pass_.pipeline);
wgpuRenderPassEncoderSetBindGroup(pass, 0, pass_.bind_group, 0, nullptr);
@@ -313,86 +357,162 @@ void MovingEllipseEffect::render(WGPURenderPassEncoder pass, float t, float b, f
}
// --- ParticleSprayEffect ---
-ParticleSprayEffect::ParticleSprayEffect(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format) : queue_(queue) {
- uniforms_ = gpu_create_buffer(device, sizeof(float) * 4, WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
- std::vector<Particle> init_p(NUM_PARTICLES); for (auto &p : init_p) p.pos[3] = 0.0f;
- particles_buffer_ = gpu_create_buffer(device, sizeof(Particle) * NUM_PARTICLES, WGPUBufferUsage_Storage | WGPUBufferUsage_Vertex, init_p.data());
- ResourceBinding cb[] = {{particles_buffer_, WGPUBufferBindingType_Storage}, {uniforms_, WGPUBufferBindingType_Uniform}};
- compute_pass_ = gpu_create_compute_pass(device, particle_spray_compute_wgsl, cb, 2);
+ParticleSprayEffect::ParticleSprayEffect(WGPUDevice device, WGPUQueue queue,
+ WGPUTextureFormat format)
+ : queue_(queue) {
+ uniforms_ =
+ gpu_create_buffer(device, sizeof(float) * 4,
+ WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
+ std::vector<Particle> init_p(NUM_PARTICLES);
+ for (auto &p : init_p)
+ p.pos[3] = 0.0f;
+ particles_buffer_ = gpu_create_buffer(
+ device, sizeof(Particle) * NUM_PARTICLES,
+ WGPUBufferUsage_Storage | WGPUBufferUsage_Vertex, init_p.data());
+ ResourceBinding cb[] = {{particles_buffer_, WGPUBufferBindingType_Storage},
+ {uniforms_, WGPUBufferBindingType_Uniform}};
+ compute_pass_ =
+ gpu_create_compute_pass(device, particle_spray_compute_wgsl, cb, 2);
compute_pass_.workgroup_size_x = (NUM_PARTICLES + 63) / 64;
- ResourceBinding rb[] = {{particles_buffer_, WGPUBufferBindingType_ReadOnlyStorage}, {uniforms_, WGPUBufferBindingType_Uniform}};
- render_pass_ = gpu_create_render_pass(device, format, particle_render_wgsl, rb, 2);
- render_pass_.vertex_count = 6; render_pass_.instance_count = NUM_PARTICLES;
+ ResourceBinding rb[] = {
+ {particles_buffer_, WGPUBufferBindingType_ReadOnlyStorage},
+ {uniforms_, WGPUBufferBindingType_Uniform}};
+ render_pass_ =
+ gpu_create_render_pass(device, format, particle_render_wgsl, rb, 2);
+ render_pass_.vertex_count = 6;
+ render_pass_.instance_count = NUM_PARTICLES;
}
-void ParticleSprayEffect::compute(WGPUCommandEncoder e, float t, float b, float i, float a) {
- struct { float i, a, t, b; } u = {i, a, t, b};
+void ParticleSprayEffect::compute(WGPUCommandEncoder e, float t, float b,
+ float i, float a) {
+ struct {
+ float i, a, t, b;
+ } u = {i, a, t, b};
wgpuQueueWriteBuffer(queue_, uniforms_.buffer, 0, &u, sizeof(u));
WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(e, nullptr);
wgpuComputePassEncoderSetPipeline(pass, compute_pass_.pipeline);
- wgpuComputePassEncoderSetBindGroup(pass, 0, compute_pass_.bind_group, 0, nullptr);
- wgpuComputePassEncoderDispatchWorkgroups(pass, compute_pass_.workgroup_size_x, 1, 1);
+ wgpuComputePassEncoderSetBindGroup(pass, 0, compute_pass_.bind_group, 0,
+ nullptr);
+ wgpuComputePassEncoderDispatchWorkgroups(pass, compute_pass_.workgroup_size_x,
+ 1, 1);
wgpuComputePassEncoderEnd(pass);
}
-void ParticleSprayEffect::render(WGPURenderPassEncoder pass, float t, float b, float i, float a) {
+void ParticleSprayEffect::render(WGPURenderPassEncoder pass, float t, float b,
+ float i, float a) {
wgpuRenderPassEncoderSetPipeline(pass, render_pass_.pipeline);
- wgpuRenderPassEncoderSetBindGroup(pass, 0, render_pass_.bind_group, 0, nullptr);
+ wgpuRenderPassEncoderSetBindGroup(pass, 0, render_pass_.bind_group, 0,
+ nullptr);
wgpuRenderPassEncoderDraw(pass, 6, NUM_PARTICLES, 0, 0);
}
// --- PostProcess Implementation Helper ---
-static void pp_update_bind_group(WGPUDevice device, WGPURenderPipeline pipeline, WGPUBindGroup *bind_group, WGPUTextureView input_view, GpuBuffer uniforms) {
- if (*bind_group) wgpuBindGroupRelease(*bind_group);
+static void pp_update_bind_group(WGPUDevice device, WGPURenderPipeline pipeline,
+ WGPUBindGroup *bind_group,
+ WGPUTextureView input_view,
+ GpuBuffer uniforms) {
+ if (*bind_group)
+ wgpuBindGroupRelease(*bind_group);
WGPUBindGroupLayout bgl = wgpuRenderPipelineGetBindGroupLayout(pipeline, 0);
- WGPUSamplerDescriptor sd = {}; sd.magFilter = WGPUFilterMode_Linear; sd.minFilter = WGPUFilterMode_Linear;
+ WGPUSamplerDescriptor sd = {};
+ sd.magFilter = WGPUFilterMode_Linear;
+ sd.minFilter = WGPUFilterMode_Linear;
WGPUSampler sampler = wgpuDeviceCreateSampler(device, &sd);
WGPUBindGroupEntry bge[3] = {};
- bge[0].binding = 0; bge[0].sampler = sampler;
- bge[1].binding = 1; bge[1].textureView = input_view;
- bge[2].binding = 2; bge[2].buffer = uniforms.buffer; bge[2].size = uniforms.size;
- WGPUBindGroupDescriptor bgd = {.layout = bgl, .entryCount = 3, .entries = bge};
+ bge[0].binding = 0;
+ bge[0].sampler = sampler;
+ bge[1].binding = 1;
+ bge[1].textureView = input_view;
+ bge[2].binding = 2;
+ bge[2].buffer = uniforms.buffer;
+ bge[2].size = uniforms.size;
+ WGPUBindGroupDescriptor bgd = {
+ .layout = bgl, .entryCount = 3, .entries = bge};
*bind_group = wgpuDeviceCreateBindGroup(device, &bgd);
}
// --- GaussianBlurEffect ---
-GaussianBlurEffect::GaussianBlurEffect(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format) : device_(device), queue_(queue) {
- uniforms_ = gpu_create_buffer(device, sizeof(float) * 4, WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
- pipeline_ = create_post_process_pipeline(device, format, gaussian_blur_shader_wgsl);
+GaussianBlurEffect::GaussianBlurEffect(WGPUDevice device, WGPUQueue queue,
+ WGPUTextureFormat format)
+ : device_(device), queue_(queue) {
+ uniforms_ =
+ gpu_create_buffer(device, sizeof(float) * 4,
+ WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
+ pipeline_ =
+ create_post_process_pipeline(device, format, gaussian_blur_shader_wgsl);
}
-void GaussianBlurEffect::render(WGPURenderPassEncoder pass, float t, float b, float i, float a) {
- struct { float t, b, i, a; } u = {t, b, i, a}; wgpuQueueWriteBuffer(queue_, uniforms_.buffer, 0, &u, sizeof(u));
+void GaussianBlurEffect::render(WGPURenderPassEncoder pass, float t, float b,
+ float i, float a) {
+ struct {
+ float t, b, i, a;
+ } u = {t, b, i, a};
+ wgpuQueueWriteBuffer(queue_, uniforms_.buffer, 0, &u, sizeof(u));
PostProcessEffect::render(pass, t, b, i, a);
}
-void GaussianBlurEffect::update_bind_group(WGPUTextureView v) { pp_update_bind_group(device_, pipeline_, &bind_group_, v, uniforms_); }
+void GaussianBlurEffect::update_bind_group(WGPUTextureView v) {
+ pp_update_bind_group(device_, pipeline_, &bind_group_, v, uniforms_);
+}
// --- SolarizeEffect ---
-SolarizeEffect::SolarizeEffect(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format) : device_(device), queue_(queue) {
- uniforms_ = gpu_create_buffer(device, sizeof(float) * 4, WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
- pipeline_ = create_post_process_pipeline(device, format, solarize_shader_wgsl);
+SolarizeEffect::SolarizeEffect(WGPUDevice device, WGPUQueue queue,
+ WGPUTextureFormat format)
+ : device_(device), queue_(queue) {
+ uniforms_ =
+ gpu_create_buffer(device, sizeof(float) * 4,
+ WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
+ pipeline_ =
+ create_post_process_pipeline(device, format, solarize_shader_wgsl);
}
-void SolarizeEffect::render(WGPURenderPassEncoder pass, float t, float b, float i, float a) {
- struct { float t, b, i, a; } u = {t, b, i, a}; wgpuQueueWriteBuffer(queue_, uniforms_.buffer, 0, &u, sizeof(u));
+void SolarizeEffect::render(WGPURenderPassEncoder pass, float t, float b,
+ float i, float a) {
+ struct {
+ float t, b, i, a;
+ } u = {t, b, i, a};
+ wgpuQueueWriteBuffer(queue_, uniforms_.buffer, 0, &u, sizeof(u));
PostProcessEffect::render(pass, t, b, i, a);
}
-void SolarizeEffect::update_bind_group(WGPUTextureView v) { pp_update_bind_group(device_, pipeline_, &bind_group_, v, uniforms_); }
+void SolarizeEffect::update_bind_group(WGPUTextureView v) {
+ pp_update_bind_group(device_, pipeline_, &bind_group_, v, uniforms_);
+}
// --- DistortEffect ---
-DistortEffect::DistortEffect(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format) : device_(device), queue_(queue) {
- uniforms_ = gpu_create_buffer(device, sizeof(float) * 4, WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
+DistortEffect::DistortEffect(WGPUDevice device, WGPUQueue queue,
+ WGPUTextureFormat format)
+ : device_(device), queue_(queue) {
+ uniforms_ =
+ gpu_create_buffer(device, sizeof(float) * 4,
+ WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
pipeline_ = create_post_process_pipeline(device, format, distort_shader_wgsl);
}
-void DistortEffect::render(WGPURenderPassEncoder pass, float t, float b, float i, float a) {
- struct { float t, b, i, a; } u = {t, b, i, a}; wgpuQueueWriteBuffer(queue_, uniforms_.buffer, 0, &u, sizeof(u));
+void DistortEffect::render(WGPURenderPassEncoder pass, float t, float b,
+ float i, float a) {
+ struct {
+ float t, b, i, a;
+ } u = {t, b, i, a};
+ wgpuQueueWriteBuffer(queue_, uniforms_.buffer, 0, &u, sizeof(u));
PostProcessEffect::render(pass, t, b, i, a);
}
-void DistortEffect::update_bind_group(WGPUTextureView v) { pp_update_bind_group(device_, pipeline_, &bind_group_, v, uniforms_); }
+void DistortEffect::update_bind_group(WGPUTextureView v) {
+ pp_update_bind_group(device_, pipeline_, &bind_group_, v, uniforms_);
+}
// --- ChromaAberrationEffect ---
-ChromaAberrationEffect::ChromaAberrationEffect(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format) : device_(device), queue_(queue) {
- uniforms_ = gpu_create_buffer(device, sizeof(float) * 4, WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
- pipeline_ = create_post_process_pipeline(device, format, chroma_aberration_shader_wgsl);
+ChromaAberrationEffect::ChromaAberrationEffect(WGPUDevice device,
+ WGPUQueue queue,
+ WGPUTextureFormat format)
+ : device_(device), queue_(queue) {
+ uniforms_ =
+ gpu_create_buffer(device, sizeof(float) * 4,
+ WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
+ pipeline_ = create_post_process_pipeline(device, format,
+ chroma_aberration_shader_wgsl);
}
-void ChromaAberrationEffect::render(WGPURenderPassEncoder pass, float t, float b, float i, float a) {
- struct { float t, b, i, a; } u = {t, b, i, a}; wgpuQueueWriteBuffer(queue_, uniforms_.buffer, 0, &u, sizeof(u));
+void ChromaAberrationEffect::render(WGPURenderPassEncoder pass, float t,
+ float b, float i, float a) {
+ struct {
+ float t, b, i, a;
+ } u = {t, b, i, a};
+ wgpuQueueWriteBuffer(queue_, uniforms_.buffer, 0, &u, sizeof(u));
PostProcessEffect::render(pass, t, b, i, a);
}
-void ChromaAberrationEffect::update_bind_group(WGPUTextureView v) { pp_update_bind_group(device_, pipeline_, &bind_group_, v, uniforms_); }
+void ChromaAberrationEffect::update_bind_group(WGPUTextureView v) {
+ pp_update_bind_group(device_, pipeline_, &bind_group_, v, uniforms_);
+}
diff --git a/src/gpu/effect.cc b/src/gpu/effect.cc
index 0ab476b..c3bd99a 100644
--- a/src/gpu/effect.cc
+++ b/src/gpu/effect.cc
@@ -188,11 +188,12 @@ void MainSequence::render_frame(float global_time, float beat, float peak,
WGPUTextureView final_view = wgpuTextureCreateView(st.texture, nullptr);
passthrough_effect_->update_bind_group(framebuffer_view_a_);
- WGPURenderPassColorAttachment final_attachment = {
- .view = final_view, .loadOp = WGPULoadOp_Load, .storeOp = WGPUStoreOp_Store};
- WGPURenderPassDescriptor final_desc = {.colorAttachmentCount = 1,
- .colorAttachments =
- &final_attachment};
+ WGPURenderPassColorAttachment final_attachment = {.view = final_view,
+ .loadOp = WGPULoadOp_Load,
+ .storeOp =
+ WGPUStoreOp_Store};
+ WGPURenderPassDescriptor final_desc = {
+ .colorAttachmentCount = 1, .colorAttachments = &final_attachment};
WGPURenderPassEncoder final_pass =
wgpuCommandEncoderBeginRenderPass(encoder, &final_desc);
passthrough_effect_->render(final_pass, 0, 0, 0, aspect_ratio);
@@ -210,16 +211,19 @@ void MainSequence::render_frame(float global_time, float beat, float peak,
wgpuSurfaceGetCurrentTexture(surface, &st);
WGPUTextureView current_output =
- is_last ? wgpuTextureCreateView(st.texture, nullptr)
- : (current_input == framebuffer_view_a_ ? framebuffer_view_b_
- : framebuffer_view_a_);
+ is_last
+ ? wgpuTextureCreateView(st.texture, nullptr)
+ : (current_input == framebuffer_view_a_ ? framebuffer_view_b_
+ : framebuffer_view_a_);
PostProcessEffect *pp =
static_cast<PostProcessEffect *>(post_effects[i]->effect.get());
pp->update_bind_group(current_input);
- WGPURenderPassColorAttachment pp_attachment = {
- .view = current_output, .loadOp = WGPULoadOp_Load, .storeOp = WGPUStoreOp_Store};
+ WGPURenderPassColorAttachment pp_attachment = {.view = current_output,
+ .loadOp = WGPULoadOp_Load,
+ .storeOp =
+ WGPUStoreOp_Store};
WGPURenderPassDescriptor pp_desc = {.colorAttachmentCount = 1,
.colorAttachments = &pp_attachment};
WGPURenderPassEncoder pp_pass =
@@ -242,10 +246,14 @@ void MainSequence::render_frame(float global_time, float beat, float peak,
}
void MainSequence::shutdown() {
- if (framebuffer_view_a_) wgpuTextureViewRelease(framebuffer_view_a_);
- if (framebuffer_a_) wgpuTextureRelease(framebuffer_a_);
- if (framebuffer_view_b_) wgpuTextureViewRelease(framebuffer_view_b_);
- if (framebuffer_b_) wgpuTextureRelease(framebuffer_b_);
+ if (framebuffer_view_a_)
+ wgpuTextureViewRelease(framebuffer_view_a_);
+ if (framebuffer_a_)
+ wgpuTextureRelease(framebuffer_a_);
+ if (framebuffer_view_b_)
+ wgpuTextureViewRelease(framebuffer_view_b_);
+ if (framebuffer_b_)
+ wgpuTextureRelease(framebuffer_b_);
for (auto &entry : sequences_) {
entry.seq->reset();
}
@@ -256,7 +264,8 @@ void MainSequence::simulate_until(float target_time, float step_rate) {
const float bpm = 128.0f;
const float aspect_ratio = 16.0f / 9.0f;
for (float t = 0.0f; t < target_time; t += step_rate) {
- WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
+ WGPUCommandEncoder encoder =
+ wgpuDeviceCreateCommandEncoder(device, nullptr);
float beat = fmodf(t * bpm / 60.0f, 1.0f);
std::vector<SequenceItem *> scene_effects, post_effects;
for (auto &entry : sequences_) {
@@ -266,7 +275,8 @@ void MainSequence::simulate_until(float target_time, float step_rate) {
}
}
for (const auto &item : scene_effects) {
- item->effect->compute(encoder, t - item->start_time, beat, 0.0f, aspect_ratio);
+ item->effect->compute(encoder, t - item->start_time, beat, 0.0f,
+ aspect_ratio);
}
WGPUCommandBuffer commands = wgpuCommandEncoderFinish(encoder, nullptr);
wgpuQueueSubmit(queue, 1, &commands);
diff --git a/src/gpu/effect.h b/src/gpu/effect.h
index 5f49041..ba569c2 100644
--- a/src/gpu/effect.h
+++ b/src/gpu/effect.h
@@ -22,10 +22,13 @@ public:
virtual ~Effect() = default;
// One-time setup (load assets, create buffers).
- virtual void init(MainSequence *demo) { (void)demo; }
+ virtual void init(MainSequence *demo) {
+ (void)demo;
+ }
// Called when the effect starts playing in a sequence segment.
- virtual void start() {}
+ virtual void start() {
+ }
// Dispatch compute shaders.
virtual void compute(WGPUCommandEncoder encoder, float time, float beat,
@@ -42,19 +45,25 @@ public:
float intensity, float aspect_ratio) = 0;
// Called when the effect finishes in a sequence segment.
- virtual void end() {}
+ virtual void end() {
+ }
bool is_initialized = false;
- virtual bool is_post_process() const { return false; }
+ virtual bool is_post_process() const {
+ return false;
+ }
};
// Base class for all post-processing effects
class PostProcessEffect : public Effect {
public:
- bool is_post_process() const override { return true; }
+ bool is_post_process() const override {
+ return true;
+ }
// Post-process effects don't have a compute phase by default
- void compute(WGPUCommandEncoder, float, float, float, float) override {}
+ void compute(WGPUCommandEncoder, float, float, float, float) override {
+ }
// Fullscreen quad render
void render(WGPURenderPassEncoder pass, float time, float beat,
diff --git a/src/gpu/gpu.cc b/src/gpu/gpu.cc
index db79b9d..b9545bf 100644
--- a/src/gpu/gpu.cc
+++ b/src/gpu/gpu.cc
@@ -3,9 +3,9 @@
// Driven by audio peaks for synchronized visual effects.
#include "gpu.h"
-#include "platform.h"
#include "demo_effects.h"
#include "effect.h"
+#include "platform.h"
#include <GLFW/glfw3.h>
#include <math.h>
@@ -23,19 +23,21 @@
// --- WebGPU Headers & Compatibility ---
#if defined(DEMO_CROSS_COMPILE_WIN32)
// Renamed Types/Enums
-#define WGPUSType_ShaderSourceWGSL WGPUSType_ShaderModuleWGSLDescriptor
-using WGPUShaderSourceWGSL = WGPUShaderModuleWGSLDescriptor;
-#define WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal WGPUSurfaceGetCurrentTextureStatus_Success
-#define WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal WGPUSurfaceGetCurrentTextureStatus_Success
+#define WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal \
+ WGPUSurfaceGetCurrentTextureStatus_Success
+#define WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal \
+ WGPUSurfaceGetCurrentTextureStatus_Success
#define WGPUCallbackMode_WaitAnyOnly 0
-static void wgpuInstanceWaitAny(WGPUInstance instance, size_t, void *, uint64_t) {
+static void wgpuInstanceWaitAny(WGPUInstance instance, size_t, void *,
+ uint64_t) {
wgpuInstanceProcessEvents(instance);
}
static void set_error_callback(WGPUDevice device, WGPUErrorCallback callback) {
wgpuDeviceSetUncapturedErrorCallback(device, callback, nullptr);
}
#else
-static void set_error_callback(WGPUDevice device, WGPUUncapturedErrorCallback callback) {
+static void set_error_callback(WGPUDevice device,
+ WGPUUncapturedErrorCallback callback) {
// Handled in descriptor for new API.
}
#endif
diff --git a/src/gpu/gpu.h b/src/gpu/gpu.h
index dd4fbd7..8aa290a 100644
--- a/src/gpu/gpu.h
+++ b/src/gpu/gpu.h
@@ -13,19 +13,27 @@
#include <webgpu/webgpu.h>
#include <webgpu/wgpu.h>
using WGPUStringView = const char *;
-static inline const char *str_view(const char *str) { return str; }
-static inline const char *label_view(const char *str) { return str; }
+static inline const char *str_view(const char *str) {
+ return str;
+}
+static inline const char *label_view(const char *str) {
+ return str;
+}
+#define WGPUSType_ShaderSourceWGSL WGPUSType_ShaderModuleWGSLDescriptor
+using WGPUShaderSourceWGSL = WGPUShaderModuleWGSLDescriptor;
#else
// Native (macOS/Linux) using newer wgpu-native
#include <webgpu.h>
#include <wgpu.h>
static inline WGPUStringView str_view(const char *str) {
- if (!str) return {nullptr, 0};
+ if (!str)
+ return {nullptr, 0};
return {str, strlen(str)};
}
static inline WGPUStringView label_view(const char *str) {
#ifndef STRIP_ALL
- if (!str) return {nullptr, 0};
+ if (!str)
+ return {nullptr, 0};
return {str, strlen(str)};
#else
(void)str;
@@ -78,7 +86,8 @@ GpuBuffer gpu_create_buffer(WGPUDevice device, size_t size, uint32_t usage,
ComputePass gpu_create_compute_pass(WGPUDevice device, const char *shader_code,
ResourceBinding *bindings,
int num_bindings);
-RenderPass gpu_create_render_pass(WGPUDevice device,
- WGPUTextureFormat format, // Needed for render pipeline
- const char *shader_code,
- ResourceBinding *bindings, int num_bindings);
+RenderPass
+gpu_create_render_pass(WGPUDevice device,
+ WGPUTextureFormat format, // Needed for render pipeline
+ const char *shader_code, ResourceBinding *bindings,
+ int num_bindings);
diff --git a/src/main.cc b/src/main.cc
index 0bd0580..aa24152 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -43,8 +43,8 @@ int register_spec_asset(AssetId id) {
return synth_register_spectrogram(&spec);
}
-static float *g_spec_buffer_a[SPEC_FRAMES * DCT_SIZE] = { 0 };
-static float *g_spec_buffer_b[SPEC_FRAMES * DCT_SIZE] = { 0 };
+static float *g_spec_buffer_a[SPEC_FRAMES * DCT_SIZE] = {0};
+static float *g_spec_buffer_b[SPEC_FRAMES * DCT_SIZE] = {0};
// Global storage for the melody to ensure it persists
std::vector<float> g_melody_data;
@@ -110,9 +110,9 @@ int generate_melody() {
return synth_register_spectrogram(&spec);
}
-float* generate_tone(float *buffer, float freq) {
+float *generate_tone(float *buffer, float freq) {
if (buffer == nullptr) {
- buffer = (float*)calloc(SPEC_FRAMES * DCT_SIZE, sizeof(float));
+ buffer = (float *)calloc(SPEC_FRAMES * DCT_SIZE, sizeof(float));
} else {
memset(buffer, 0, SPEC_FRAMES * DCT_SIZE * sizeof(float));
}
@@ -159,8 +159,8 @@ int main(int argc, char **argv) {
int hihat_id = register_spec_asset(AssetId::ASSET_HIHAT_1);
// Still keep the dynamic tone for bass
- const float* g_spec_buffer_a = generate_tone(nullptr, 110.0f); // A2
- const float* g_spec_buffer_b = generate_tone(nullptr, 110.0f);
+ const float *g_spec_buffer_a = generate_tone(nullptr, 110.0f); // A2
+ const float *g_spec_buffer_b = generate_tone(nullptr, 110.0f);
const Spectrogram bass_spec = {g_spec_buffer_a, g_spec_buffer_b, SPEC_FRAMES};
int bass_id = synth_register_spectrogram(&bass_spec);
@@ -173,7 +173,7 @@ int main(int argc, char **argv) {
auto update_game_logic = [&](double t) {
if (t - last_beat_time > SECONDS_PER_BEAT / 2.0) { // 8th notes
- last_beat_time = t; // Sync to t
+ last_beat_time = t; // Sync to t
const int step = beat_count % 16;
@@ -210,15 +210,15 @@ int main(int argc, char **argv) {
#ifndef STRIP_ALL
if (seek_time > 0.0) {
printf("Seeking to %.2f seconds...\n", seek_time);
-
+
// Simulate audio/game logic
// We step at ~60hz
- const double step = 1.0/60.0;
+ const double step = 1.0 / 60.0;
for (double t = 0.0; t < seek_time; t += step) {
update_game_logic(t);
audio_render_silent((float)step);
}
-
+
// Simulate Visuals
gpu_simulate_until((float)seek_time);
}
@@ -231,7 +231,7 @@ int main(int argc, char **argv) {
platform_poll();
double current_time = platform_get_time() + seek_time; // Offset logic time
-
+
update_game_logic(current_time);
int width, height;
diff --git a/tools/seq_compiler.cc b/tools/seq_compiler.cc
index 8da4e4e..fabb43f 100644
--- a/tools/seq_compiler.cc
+++ b/tools/seq_compiler.cc
@@ -78,14 +78,15 @@ int main(int argc, char *argv[]) {
<< ": EFFECT requires <Class> <start> <end> <priority>\n";
return 1;
}
-
+
// Capture remaining args
std::string extra_args;
std::getline(ss, extra_args); // Read rest of line
- // Remove leading whitespace from getline if any (getline reads the space after priority)
+ // Remove leading whitespace from getline if any (getline reads the space
+ // after priority)
extra_args = trim(extra_args);
if (!extra_args.empty()) {
- extra_args = ", " + extra_args;
+ extra_args = ", " + extra_args;
}
current_seq->effects.push_back(
@@ -114,8 +115,9 @@ int main(int argc, char *argv[]) {
out_file << " auto seq = std::make_shared<Sequence>();\n";
for (const auto &eff : seq.effects) {
out_file << " seq->add_effect(std::make_shared<" << eff.class_name
- << ">(device, queue, format" << eff.extra_args << "), "
- << eff.start << "f, " << eff.end << "f, " << eff.priority << ");\n";
+ << ">(device, queue, format" << eff.extra_args << "), "
+ << eff.start << "f, " << eff.end << "f, " << eff.priority
+ << ");\n";
}
out_file << " main_seq.add_sequence(seq, " << seq.start_time << "f, "
<< seq.priority << ");\n";
@@ -123,8 +125,9 @@ int main(int argc, char *argv[]) {
}
out_file << "}\n";
-
- std::cout << "Successfully generated timeline with " << sequences.size() << " sequences.\n";
+
+ std::cout << "Successfully generated timeline with " << sequences.size()
+ << " sequences.\n";
return 0;
}