diff options
Diffstat (limited to 'doc/archive/HANDOFF_2026-02-08.md')
| -rw-r--r-- | doc/archive/HANDOFF_2026-02-08.md | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/doc/archive/HANDOFF_2026-02-08.md b/doc/archive/HANDOFF_2026-02-08.md new file mode 100644 index 0000000..f796f05 --- /dev/null +++ b/doc/archive/HANDOFF_2026-02-08.md @@ -0,0 +1,359 @@ +# Handoff: Shader Parametrization System (February 8, 2026) + +## Summary +Completed comprehensive shader parametrization system enabling dynamic per-frame parameters for visual effects via uniform buffers and .seq file syntax. + +## Work Completed ✅ + +### Shader Parametrization System (Task #73 Phase 0) +**Goal**: Enable artists to configure visual effects with parameters (color, intensity, decay rates) via .seq files without touching C++ code. + +**Use Cases**: Flash effect with custom colors, chromatic aberration strength control, blur radius adjustment, distortion parameters. + +**Implementation**: + +#### Phase 1: UniformHelper Template +- Created `src/gpu/uniform_helper.h` - Generic type-safe wrapper for WebGPU uniform buffers +- Template class handles buffer creation, updates, and lifetime management +- Zero-overhead abstraction over `gpu_create_buffer()` and `wgpuQueueWriteBuffer()` + +```cpp +template <typename T> +class UniformBuffer { + void init(WGPUDevice device); + void update(WGPUQueue queue, const T& data); + GpuBuffer& get(); +}; +``` + +#### Phase 2: FlashEffect Parameter Structs +- Added `FlashEffectParams` (constructor-time base parameters): + - `color[3]` - RGB flash color (default: white) + - `decay_rate` - Flash fade rate per frame (default: 0.98) + - `trigger_threshold` - Intensity threshold to trigger flash (default: 0.7) + +- Added `FlashUniforms` (GPU buffer layout with WGSL alignment): + - `flash_intensity` (4 bytes, offset 0) + - `intensity` (4 bytes, offset 4) + - `_pad1[2]` (8 bytes, offset 8-15) - **Padding for vec3 alignment** + - `color[3]` (12 bytes, offset 16-27) - **Aligned to 16 bytes** + - `_pad2` (4 bytes, offset 28-31) + - Total: 32 bytes (enforced with `static_assert`) + +#### Phase 3: Parameterized WGSL Shader +- Updated `flash_effect.cc` shader to use `uniforms.flash_color` instead of hardcoded white +- Shader bindings: sampler (0), texture (1), uniforms (2) +- Fragment shader mixes input color with parameterized flash color based on flash intensity + +```wgsl +struct Uniforms { + flash_intensity: f32, + intensity: f32, + flash_color: vec3<f32>, // Parameterized color + _pad: f32, +}; + +fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> { + let color = textureSample(inputTexture, inputSampler, input.uv); + var flashed = mix(color.rgb, uniforms.flash_color, uniforms.flash_intensity); + return vec4<f32>(flashed, color.a); +} +``` + +#### Phase 4: Per-Frame Parameter Computation +- Implemented dynamic parameter animation in `FlashEffect::render()` method +- Parameters computed each frame based on time, beat, and intensity +- Example: Color modulated by sinusoidal functions of time and beat + +```cpp +// Animate color based on time and beat +const float r = params_.color[0] * (0.5f + 0.5f * sinf(time * 0.5f)); +const float g = params_.color[1] * (0.5f + 0.5f * cosf(time * 0.7f)); +const float b = params_.color[2] * (1.0f + 0.3f * beat); + +const FlashUniforms u = { + .flash_intensity = flash_intensity_, + .intensity = intensity, + ._pad1 = {0.0f, 0.0f}, + .color = {r, g, b}, + .pad2 = 0.0f +}; +uniforms_.update(ctx_.queue, u); +``` + +#### Phase 5: .seq Syntax Extension +- Extended `seq_compiler.cc` to parse `key=value` parameters after effect class name +- Added `parse_parameters()` function to extract parameter pairs +- Code generation creates `FlashEffectParams` struct initialization for parameterized effects +- Backward compatibility: Effects without parameters use default constructor + +**Syntax Example**: +``` +EFFECT + FlashEffect 0 1 color=1.0,0.5,0.5 decay=0.95 +``` + +**Generated Code**: +```cpp +{ + FlashEffectParams p; + p.color[0] = 1.0f; + p.color[1] = 0.5f; + p.color[2] = 0.5f; + p.decay_rate = 0.95f; + seq->add_effect(std::make_shared<FlashEffect>(ctx, p), 0.0f, 1.f, 0); +} +``` + +--- + +### Critical Bugfix: WGSL Alignment +**Problem**: WebGPU validation error "Buffer is bound with size 24 where the shader expects 32" + +**Root Cause**: WGSL alignment rules require `vec3<f32>` to be 16-byte aligned despite having 12-byte size. Initial `FlashUniforms` struct layout was: +```cpp +struct FlashUniforms { + float flash_intensity; // 0-3 + float intensity; // 4-7 + float color[3]; // 8-19 (WRONG - no padding) + float _pad; // 20-23 +}; // Total: 24 bytes (WRONG) +``` + +**Solution**: Added explicit padding to align `color` array to 16-byte boundary: +```cpp +struct FlashUniforms { + float flash_intensity; // 0-3 + float intensity; // 4-7 + float _pad1[2]; // 8-15 (padding) + float color[3]; // 16-27 (aligned to 16 bytes) + float _pad2; // 28-31 +}; // Total: 32 bytes (CORRECT) +static_assert(sizeof(FlashUniforms) == 32, "FlashUniforms must be 32 bytes"); +``` + +**Impact**: Demo now runs without validation errors, all 32/32 tests pass. + +--- + +## Files Modified + +**New Files (3)**: +- `src/gpu/uniform_helper.h` - UniformBuffer template class +- `src/tests/test_uniform_helper.cc` - Unit test for template compilation +- `doc/SHADER_PARAMETRIZATION_PLAN.md` - Complete design document + +**Modified Files (11)**: +- `src/gpu/effects/flash_effect.h` - Added FlashEffectParams, FlashUniforms structs, parameterized constructor +- `src/gpu/effects/flash_effect.cc` - Implemented per-frame computation, updated shader with parameterized color +- `src/gpu/demo_effects.h` - Removed duplicate FlashEffect definition, added include +- `tools/seq_compiler.cc` - Added parameter parsing and code generation +- `assets/demo.seq` - Added example with parameters +- `src/generated/timeline.cc` - Generated code with struct initialization +- `CMakeLists.txt` - Added test_uniform_helper target +- `TODO.md` - Added Task #73 (extend to other effects), moved completion to summary +- `PROJECT_CONTEXT.md` - Updated "Recently Completed" section +- `doc/COMPLETED.md` - Added detailed completion entry +- `doc/HANDOFF_2026-02-08.md` - This document + +--- + +## Commits Made + +**c7d1dd7** - `feat(gpu): Implement shader parametrization system` +- Phases 1-5 implementation +- 11 files changed (808+ / 40-) +- UniformHelper template + FlashEffect parametrization + .seq syntax + +**775c0ea** - `fix(gpu): Correct FlashUniforms struct alignment for WGSL` +- Critical alignment bugfix (24 → 32 bytes) +- Added static_assert for future safety +- Fixed validation error + +--- + +## Test Results + +**All 32/32 tests passing (100%)** + +**Test Coverage**: +- `test_uniform_helper.cc` - Verifies UniformBuffer template compiles correctly +- `test_demo_effects.cc` - All post-process and scene effects instantiate successfully +- Full shader compilation tests pass with new parameterized shaders + +**Verification**: +- Demo runs without WebGPU validation errors +- Visual effects render with parameterized colors +- .seq file parsing generates correct parameter initialization code +- Per-frame animation produces time-dependent color modulation + +--- + +## Current Status + +**Completed:** +- ✅ Full shader parametrization infrastructure +- ✅ FlashEffect fully parameterized with color/decay control +- ✅ .seq syntax extension with key=value parsing +- ✅ Per-frame dynamic parameter computation +- ✅ Critical WGSL alignment bug fixed +- ✅ Documentation updated (TODO.md, PROJECT_CONTEXT.md, COMPLETED.md) + +**Ready for:** +- Task #73: Extend parametrization to other effects (ChromaAberrationEffect, GaussianBlurEffect, DistortEffect, SolarizeEffect) +- Additional parameter types (vec2, vec4, enums) +- Parameter curve system for keyframe animation (future) + +--- + +## Technical Notes + +### WGSL Alignment Rules +**Critical for future implementations:** +- `vec3<f32>` has **size = 12 bytes** but **alignment = 16 bytes** +- Always add padding before vec3 fields to align to 16-byte boundary +- Use `static_assert(sizeof(YourStruct) == expected_size)` to catch misalignment +- Reference: [WebGPU WGSL Spec - Alignment and Size](https://www.w3.org/TR/WGSL/#alignment-and-size) + +### UniformHelper Pattern +**Reusable template for any effect parameters:** +```cpp +// 1. Define parameter structs +struct YourEffectParams { /* constructor-time params */ }; +struct YourEffectUniforms { /* GPU buffer layout with padding */ }; +static_assert(sizeof(YourEffectUniforms) == expected_size); + +// 2. Add UniformBuffer member +UniformBuffer<YourEffectUniforms> uniforms_; + +// 3. Initialize in constructor +uniforms_.init(ctx_.device); + +// 4. Update in render() +const YourEffectUniforms u = { /* compute values */ }; +uniforms_.update(ctx_.queue, u); + +// 5. Bind in shader +pipeline_ = create_pipeline(...); +bind_group_ = create_bind_group(..., uniforms_.get().buffer, ...); +``` + +### Backward Compatibility +**All existing effects continue to work:** +- Default parameter constructor delegates to parameterized constructor +- Effects without .seq parameters use default values +- No changes required to existing timeline code + +--- + +## Design Document + +**Complete design**: See `doc/SHADER_PARAMETRIZATION_PLAN.md` + +**Key Sections**: +- Motivation and use cases +- 5-phase implementation plan +- WGSL alignment rules and solutions +- Per-frame vs constructor-time parameters +- .seq syntax specification +- Migration path for existing effects +- Size budget analysis (~400-500 bytes) +- Alternative approaches considered + +--- + +## Size Impact + +**Binary Size**: +400-500 bytes net +- UniformHelper template code: ~200 bytes +- FlashEffectParams/Uniforms structs: ~100 bytes +- Per-effect parameter overhead: ~50-100 bytes each +- .seq compiler parameter parsing: ~100 bytes + +**Trade-off**: Acceptable size increase for significant artist workflow improvement (no C++ recompilation for parameter tweaks). + +--- + +## Next Steps (Recommendations) + +### Immediate (Task #73) +Extend parametrization to other effects using FlashEffect as template: + +1. **ChromaAberrationEffect**: + - Parameters: `offset` (vec2), `strength` (float) + - Syntax: `EFFECT + ChromaAberrationEffect 0 5 offset=0.01,0.02 strength=1.5` + +2. **GaussianBlurEffect**: + - Parameters: `radius` (float), `sigma` (float) + - Syntax: `EFFECT + GaussianBlurEffect 2 8 radius=5.0 sigma=2.0` + +3. **DistortEffect** (if exists): + - Parameters: `amount` (float), `speed` (float), `scale` (vec2) + +4. **SolarizeEffect**: + - Parameters: `threshold` (float), `intensity` (float) + +### Future Enhancements +- Parameter curve system (keyframe animation via .seq timeline) +- vec4/mat4 parameter support (color with alpha, transformation matrices) +- Enum parameters (blend modes, filter types) +- Parameter validation and clamping (min/max ranges) + +--- + +## Context for Next Session + +### What Works +- Shader parametrization infrastructure fully functional +- FlashEffect demonstrates complete implementation pattern +- .seq syntax parsing robust with backward compatibility +- All tests passing, demo stable + +### Known Limitations +- Only FlashEffect parametrized (other effects use hardcoded values) +- No parameter validation or range clamping +- No keyframe animation support (future feature) + +### Migration Pattern for Other Effects +1. Copy `FlashEffectParams` / `FlashUniforms` pattern +2. Add `UniformBuffer<YourUniforms>` member +3. Update shader to use uniform values +4. Implement per-frame computation in `render()` +5. Extend `seq_compiler.cc` with effect-specific parameter parsing +6. Test with .seq file, verify alignment with static_assert + +--- + +## User Feedback Summary + +**Session Start**: User requested shader parametrization with use cases (flash colors, aberration strength) + +**Key Clarifications**: +- User confirmed parameters will be "generated in the code (manually, in effect's C++ code)" +- User emphasized "precision: user change parameter values on a per-frame basis. time-dependent" +- Critical feedback: Per-frame computation required, not just static constructor params + +**Critical Bug Report**: User provided log.txt showing GPU validation error (buffer size mismatch) + +**Outcome**: User satisfied, requested commit + documentation update (completed) + +--- + +## Handoff Checklist + +- [x] All tests passing (32/32) +- [x] Working tree clean +- [x] Documentation updated (TODO.md, PROJECT_CONTEXT.md, COMPLETED.md) +- [x] Commits created with detailed messages (c7d1dd7, 775c0ea) +- [x] No known regressions +- [x] Design document complete (SHADER_PARAMETRIZATION_PLAN.md) +- [x] Extension task noted (Task #73) +- [x] Ready for next session + +--- + +**handoff(Claude):** Shader parametrization system complete. FlashEffect fully parameterized with .seq syntax. Critical alignment bug fixed. 32/32 tests passing. Ready for extension to other effects (Task #73). + +--- + +*Generated: February 8, 2026* +*Claude Sonnet 4.5* |
