# Contributing Guidelines ## Commit Policy ### Verify Before Committing **Automated (Recommended):** ```bash ./scripts/check_all.sh ``` Runs tests, builds tools, cross-compiles Windows. **Manual:** ```bash # 1. Tests cmake -S . -B build -DDEMO_BUILD_TESTS=ON -DDEMO_BUILD_TOOLS=ON cmake --build build -j4 cd build && ctest --output-on-failure # 2. Windows (if mingw-w64 installed) ./scripts/build_win.sh ``` ### Debug Logging Verification ```bash cmake -S . -B build_debug_check -DDEMO_ENABLE_DEBUG_LOGS=ON cmake --build build_debug_check -j4 ``` Must compile without errors. **Debug macros** (`src/util/debug.h`): - `DEBUG_LOG_AUDIO`, `DEBUG_LOG_RING_BUFFER`, `DEBUG_LOG_TRACKER` - `DEBUG_LOG_SYNTH`, `DEBUG_LOG_3D`, `DEBUG_LOG_ASSETS`, `DEBUG_LOG_GPU` Example: ```cpp #if defined(DEBUG_LOG_AUDIO) DEBUG_AUDIO("[CALLBACK #%d] frames=%d\n", ++count, frames); #endif ``` ### Code Formatting ```bash clang-format -i $(git ls-files | grep -E '\.(h|cc)$' | grep -vE '^(assets|archive|third_party)/') ``` Never format `third_party/`. ### File Requirements - Newline at end of file - 3-line header comment - Max 500 lines (split if larger) ## Coding Style ### Core Rules - `const` everywhere possible - `const T* name` not `const T *name` - Pre-increment `++x` not `x++` - Spaces around operators: `x = (a + b) * c;` - No trailing whitespace - No `auto` (except complex iterators) - No C++ casts (`static_cast`, `reinterpret_cast`) ### Preprocessor ```cpp #if defined(MY_TAG) ... #endif /* defined(MY_TAG) */ ``` ### Struct Initialization ```cpp // Good const WGPUDescriptor desc = { .format = g_format, .dimension = WGPUTextureViewDimension_2D, }; // Bad WGPUDescriptor desc = {}; desc.format = g_format; desc.dimension = WGPUTextureViewDimension_2D; ``` ### Class Keywords ```cpp private: // 1 space indent int field_; ``` ### Comments - 1-line comment for non-obvious functions - 3-line header for all source files ## Development Protocols ### Adding Visual Effect 1. Implement `Effect` subclass in `src/gpu/demo_effects.cc` 2. Add to `assets/demo.seq` 3. **Update `test_demo_effects.cc`**: - Add to test list - Increment `EXPECTED_*_COUNT` 4. Verify: ```bash cmake -S . -B build -DDEMO_BUILD_TESTS=ON cmake --build build -j4 --target test_demo_effects cd build && ./test_demo_effects ``` ### Audio Initialization **Production:** ```cpp audio_init(); static AudioEngine g_audio_engine; g_audio_engine.init(); g_audio_engine.update(music_time); ``` **Tests:** ```cpp AudioEngine engine; engine.init(); engine.update(1.0f); engine.shutdown(); ``` Direct synth APIs (`synth_register_spectrogram`, `synth_trigger_voice`, etc.) are valid for performance-critical code. ### Fatal Error Checking Use `src/util/fatal_error.h` for programming errors only: ```cpp // Most common (90%) FATAL_CHECK(pos < capacity, "overflow: %d >= %d\n", pos, capacity); // Unconditional FATAL_ERROR("Invalid state: %d\n", state); // Unreachable switch (type) { case A: return handle_a(); default: FATAL_UNREACHABLE(); } // Assertion FATAL_ASSERT(ptr != nullptr); // Complex validation FATAL_CODE_BEGIN if (depth > MAX) FATAL_ERROR("depth=%d\n", depth); FATAL_CODE_END ``` **DO NOT** use for expected errors (file not found, network errors). **Build modes:** - Debug/STRIP_ALL: All checks enabled - FINAL_STRIP: All checks stripped (~500-600 bytes saved) **Test both:** ```bash cmake -S . -B build && cmake --build build -j4 && cd build && ctest ./scripts/build_final.sh ``` ### Script Maintenance After hierarchy changes (moving files, renaming), verify: ```bash ./scripts/check_all.sh ./scripts/gen_coverage_report.sh ``` Update scripts with hardcoded paths. ## Uniform Buffer Checklist To ensure consistency and prevent alignment-related issues, follow these guidelines when working with uniform buffers: 1. **Define WGSL Structs:** Clearly define uniform structs in WGSL, paying close attention to type alignment (`f32`, `vec2`, `vec3`, `vec4`) and using explicit padding (`_pad0: vec2`) where necessary. 2. **Mirror in C++:** Create corresponding C++ structs that mirror the WGSL struct's definitions. 3. **`static_assert` for Size:** Every C++ struct corresponding to a WGSL uniform buffer **must** have a `static_assert` verifying its size matches the expected WGSL size. Use `sizeof(MyStruct) == EXPECTED_SIZE`. 4. **Standard Bindings:** * **Binding 2:** Always use `CommonPostProcessUniforms` (or a similar common structure) for general per-frame data (resolution, time, beat, etc.). * **Binding 3:** Use effect-specific parameter structs for unique effect data. 5. **Shader Consistency:** Ensure WGSL shaders correctly declare and use uniforms at the specified bindings (`@group(0) @binding(2)` for common uniforms, `@group(0) @binding(3)` for effect parameters). 6. **Validation Script:** Run `tools/validate_uniforms.py` as part of your development workflow to catch any discrepancies in size or alignment between C++ and WGSL definitions. Ensure this script passes without errors. 7. **Documentation:** Refer to `doc/UNIFORM_BUFFER_GUIDELINES.md` for detailed information on WGSL alignment rules and best practices.