diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-09 11:17:53 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-09 11:17:53 +0100 |
| commit | fd19130b3360d17b44247ec26533b20e051b7f8c (patch) | |
| tree | f3116150299e320c4a5951aa7a2fdd1dc12a9511 /doc/UNIFORM_BUFFER_GUIDELINES.md | |
| parent | 698649d30129ba26a7ad9c13a874686640f43972 (diff) | |
feat: WGSL Uniform Buffer Validation & Consolidation (Task #75)
- Added to validate WGSL/C++ struct alignment.
- Integrated validation into .
- Standardized uniform usage in , , , .
- Renamed generic to specific names in WGSL and C++ to avoid collisions.
- Added and updated .
- handoff(Gemini): Completed Task #75.
Diffstat (limited to 'doc/UNIFORM_BUFFER_GUIDELINES.md')
| -rw-r--r-- | doc/UNIFORM_BUFFER_GUIDELINES.md | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/doc/UNIFORM_BUFFER_GUIDELINES.md b/doc/UNIFORM_BUFFER_GUIDELINES.md new file mode 100644 index 0000000..ac02223 --- /dev/null +++ b/doc/UNIFORM_BUFFER_GUIDELINES.md @@ -0,0 +1,106 @@ +# WGSL Uniform Buffer Guidelines + +This document outlines the rules and best practices for defining and using uniform buffers in WGSL shaders within this project, focusing on alignment, size, and consistency. + +## WGSL Alignment Rules + +Understanding WGSL's memory layout rules is crucial for correct uniform buffer implementation. The following are the general alignment requirements for common WGSL types: + +- `f32`: 4-byte alignment. +- `vec2<f32>`: 8-byte alignment (4 bytes per component * 2 components = 8 bytes). +- `vec3<f32>`: 16-byte alignment (4 bytes per component * 3 components = 12 bytes, padded to 16). +- `vec4<f32>`: 16-byte alignment (4 bytes per component * 4 components = 16 bytes). +- `array<T, N>`: The alignment of an array is typically the alignment of its base type `T`. + +Structs are padded to the alignment of their largest member. Any trailing space in a struct is also padded to match the maximum alignment of any member within the struct. + +## Standard Uniform Buffer Pattern + +To maintain consistency and facilitate efficient rendering, a standard pattern for uniform buffer usage is established: + +- **Binding 0 & 1:** Reserved for Sampler and Texture access (handled by `pp_update_bind_group`). +- **Binding 2:** **Common Uniforms** (`CommonPostProcessUniforms` or similar). This buffer should contain frequently used data like resolution, aspect ratio, time, beat, and audio intensity. +- **Binding 3:** **Effect-Specific Parameters**. This buffer holds parameters unique to a particular effect (e.g., `strength`, `speed`, `fade_amount`). + +This pattern ensures that common data is shared efficiently across effects, while effect-specific data remains isolated. + +## Defining Uniform Structs + +### WGSL Definitions + +When defining uniform structs in WGSL, adhere to the following: + +- **Explicit Padding:** Use padding fields (`_pad0`, `_pad1`, etc.) where necessary to ensure correct alignment, especially when mixing types of different alignment requirements (e.g., `vec2<f32>` followed by `f32`s). +- **Use `vec2<f32>` for 8-byte padding:** If you need 8 bytes of padding, use `_pad0: vec2<f32>` instead of `_pad0: f32, _pad1: f32` for potentially better clarity and to leverage WGSL's type system. +- **Minimize Padding:** Only add padding where required by alignment rules to reduce memory usage. + +**Example (CommonPostProcessUniforms / HeptagonUniforms):** + +```wgsl +struct CommonUniforms { + resolution: vec2<f32>, + _pad0: vec2<f32>, // 8 bytes padding to align subsequent members + aspect_ratio: f32, + time: f32, + beat: f32, + audio_intensity: f32, +}; +// Expected size: 32 bytes +``` + +**Example (EffectParams with f32 members):** + +```wgsl +struct EffectParams { + parameter1: f32, + parameter2: f32, + // ... more parameters ... +}; +// Expected size: 8 bytes (if only two f32s) +``` + +### C++ Definitions and Validation + +For every WGSL uniform struct, a corresponding C++ struct must exist. This C++ struct must include a `static_assert` to verify its size and alignment matches the WGSL definition. + +- **Mirror WGSL Structure:** The C++ struct should mirror the WGSL struct's member order and types as closely as possible to ensure accurate size calculation. +- **`static_assert`:** Always include `static_assert(sizeof(MyStruct) == EXPECTED_SIZE, "MyStruct must be EXPECTED_SIZE bytes for WGSL alignment");`. +- **Use `float` for `f32`:** Use `float` for `f32` in C++. +- **Use `vec2<f32>` mapping:** If WGSL uses `vec2<f32>`, map it to an equivalent C++ type that occupies 8 bytes, typically `float[2]` or a `struct Vec2 { float x, y; }` if more complex type handling is needed. +- **Padding:** C++ padding rules can differ from WGSL. Pay close attention to `static_assert` for validation. + +**Example (C++ CommonPostProcessUniforms):** + +```cpp +struct CommonPostProcessUniforms { + vec2 resolution; // 8 bytes + float _pad[2]; // 8 bytes padding (matches vec2<f32> in WGSL) + float aspect_ratio; // 4 bytes + float time; // 4 bytes + float beat; // 4 bytes + float audio_intensity; // 4 bytes +}; +static_assert(sizeof(CommonPostProcessUniforms) == 32, + "CommonPostProcessUniforms must be 32 bytes for WGSL alignment"); +``` + +**Example (C++ GaussianBlurParams):** + +```cpp +struct GaussianBlurParams { + float strength = 2.0f; + float _pad = 0.0f; +}; +static_assert(sizeof(GaussianBlurParams) == 8, + "GaussianBlurParams must be 8 bytes for WGSL alignment"); +``` + +## Handling Common Pitfalls + +- **`vec3<f32>` Padding:** Avoid using `vec3<f32>` for padding in WGSL, as it has a 16-byte alignment. If padding is needed, use `vec2<f32>` for 8 bytes or individual `f32`s for 4-byte alignment. +- **C++ vs. WGSL Alignment:** Always rely on `static_assert` in C++ and verify against WGSL alignment rules. C++ padding rules might differ, and the `static_assert` is the ultimate arbiter. +- **Unmatched Structs:** Ensure every WGSL uniform struct has a corresponding C++ struct with a matching `static_assert`. + +## Validation Tool + +The `tools/validate_uniforms.py` script is integrated into the build system. It automatically checks for inconsistencies between WGSL and C++ uniform struct definitions and reports any size mismatches. Ensure this script passes for all new or modified uniform definitions. |
