From 775c0ea61faeaa8a09638d94b2399117f8b8cea3 Mon Sep 17 00:00:00 2001 From: skal Date: Sun, 8 Feb 2026 16:33:24 +0100 Subject: fix(gpu): Correct FlashUniforms struct alignment for WGSL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Critical bugfix: Buffer size mismatch causing validation error **Problem:** Demo crashed with WebGPU validation error: "Buffer is bound with size 24 where the shader expects 32" **Root Cause:** WGSL struct alignment rules: - vec3 has 16-byte alignment (not 12-byte) - C++ struct was 24 bytes, WGSL expected 32 bytes **Incorrect Layout (24 bytes):** ```cpp struct FlashUniforms { float flash_intensity; // 0-3 float intensity; // 4-7 float color[3]; // 8-19 (WRONG: no padding) float _pad; // 20-23 }; ``` **Correct Layout (32 bytes):** ```cpp struct FlashUniforms { float flash_intensity; // 0-3 float intensity; // 4-7 float _pad1[2]; // 8-15 (padding for vec3 alignment) float color[3]; // 16-27 (vec3 aligned to 16 bytes) float _pad2; // 28-31 }; ``` **WGSL Alignment Rules:** - vec3 has size=12 bytes but alignment=16 bytes - Must pad before vec3 to maintain 16-byte boundary **Files Modified:** - src/gpu/effects/flash_effect.h (struct layout + static_assert) - src/gpu/effects/flash_effect.cc (field names: _pad → _pad1, _pad2) **Verification:** ✅ Demo runs without validation errors ✅ All 32 tests pass (100%) ✅ static_assert enforces correct size at compile time handoff(Claude): Critical alignment bug fixed, demo stable --- src/gpu/effects/flash_effect.cc | 5 +++-- src/gpu/effects/flash_effect.h | 12 ++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/gpu/effects/flash_effect.cc b/src/gpu/effects/flash_effect.cc index e02ea75..1bb4d93 100644 --- a/src/gpu/effects/flash_effect.cc +++ b/src/gpu/effects/flash_effect.cc @@ -85,8 +85,9 @@ void FlashEffect::render(WGPURenderPassEncoder pass, float time, float beat, const FlashUniforms u = { .flash_intensity = flash_intensity_, .intensity = intensity, - .color = {r, g, b}, // Time-dependent, computed every frame - ._pad = 0.0f}; + ._pad1 = {0.0f, 0.0f}, // Padding for vec3 alignment + .color = {r, g, b}, // Time-dependent, computed every frame + ._pad2 = 0.0f}; uniforms_.update(ctx_.queue, u); wgpuRenderPassEncoderSetPipeline(pass, pipeline_); diff --git a/src/gpu/effects/flash_effect.h b/src/gpu/effects/flash_effect.h index 8241557..373b48b 100644 --- a/src/gpu/effects/flash_effect.h +++ b/src/gpu/effects/flash_effect.h @@ -15,12 +15,16 @@ struct FlashEffectParams { }; // Uniform data sent to GPU shader +// IMPORTANT: Must match WGSL struct layout with proper alignment +// vec3 in WGSL has 16-byte alignment, not 12-byte! struct FlashUniforms { - float flash_intensity; - float intensity; - float color[3]; // RGB flash color - float _pad; + float flash_intensity; // offset 0 + float intensity; // offset 4 + float _pad1[2]; // offset 8-15 (padding for vec3 alignment) + float color[3]; // offset 16-27 (vec3 aligned to 16 bytes) + float _pad2; // offset 28-31 }; +static_assert(sizeof(FlashUniforms) == 32, "FlashUniforms must be 32 bytes for WGSL alignment"); class FlashEffect : public PostProcessEffect { public: -- cgit v1.2.3