# Auxiliary Texture Initialization **Technical decision document for auxiliary texture initialization order** ## Problem Auxiliary textures (inter-effect shared textures like masks) were created with incorrect dimensions, causing "half resolution" rendering bugs. ### Root Cause ```cpp // Before fix (effect.cc:180-181) entry.seq->init(this); // width_/height_ = 1280x720 (defaults) entry.seq->resize(width, height); // THEN set actual dimensions (e.g., 2560x1440) ``` Effects called `register_auxiliary_texture()` during `init()` using default dimensions (1280×720) before `resize()` set actual window size. Compute shaders received uniforms with correct resolution but rendered to wrong-sized textures. ### Affected Code - `CircleMaskEffect` - registers `"circle_mask"` texture - `CNNEffect` - registers `"captured_frame"` texture - `RotatingCubeEffect` - consumes `"circle_mask"` texture - Any effect that calls `register_auxiliary_texture()` in `init()` ## Solutions Considered ### Option 1: Lazy Initialization ❌ **Approach:** Defer texture creation until first use (compute/render). **Pros:** - Textures created with correct dimensions - No reallocation on resize if dimensions unchanged - Memory saved if effect never renders **Cons:** - Requires `ensure_texture()` guards at every access point - Cascade complexity: consumers (like RotatingCubeEffect) also need lazy bind group creation - Multiple code paths, harder to debug - Violates "initialize once" principle **Outcome:** Attempted but rejected due to complexity cascade. ### Option 2: Reorder init/resize ✅ **Approach:** Call `resize()` before `init()` to set dimensions first. ```cpp // After fix (effect.cc:179-180) entry.seq->resize(width, height); // Set dimensions FIRST entry.seq->init(this); // Then init with correct dimensions ``` **Pros:** - **Simple:** 2-line change in MainSequence - Dimensions available when needed during init() - No lazy initialization complexity - Clear, predictable initialization order **Cons:** - Effects see resize() before init() (unusual but harmless) - Base `Effect::resize()` just updates width_/height_ members **Outcome:** Implemented. Clean, maintainable solution. ## Implementation ### Changes Made **File:** `src/gpu/effect.cc` **Lines 179-180:** ```cpp entry.seq->resize(width, height); // Set dimensions FIRST entry.seq->init(this); // Then init with correct dimensions ``` **Lines 189-190:** ```cpp seq->resize(width_, height_); // Set dimensions FIRST seq->init(this); // Then init with correct dimensions ``` ### Resize Optimization Added early return in effects to avoid unnecessary GPU reallocation: ```cpp void CircleMaskEffect::resize(int width, int height) { if (width == width_ && height == height_) return; // No-op if dimensions unchanged Effect::resize(width, height); if (!demo_ || !texture_initialized_) return; demo_->resize_auxiliary_texture("circle_mask", width, height); // Recreate bind groups with new texture view... } ``` ## Guidelines for New Effects ### Creating Auxiliary Textures ```cpp void MyEffect::init(MainSequence* demo) { demo_ = demo; // width_/height_ are VALID here (set by resize() before init()) demo_->register_auxiliary_texture("my_texture", width_, height_); // Create pipelines and bind groups referencing the texture } ``` ### Consuming Auxiliary Textures ```cpp void MyEffect::init(MainSequence* demo) { demo_ = demo; // Safe to get_auxiliary_view() here - producer effects // initialized before consumers (order in timeline) WGPUTextureView view = demo_->get_auxiliary_view("circle_mask"); } ``` ### Handling Resize ```cpp void MyEffect::resize(int width, int height) { if (width == width_ && height == height_) return; // Early exit if unchanged Effect::resize(width, height); // If you registered auxiliary texture, resize it: if (demo_) { demo_->resize_auxiliary_texture("my_texture", width, height); // Recreate bind groups with new texture view } } ``` ## Testing All 36 tests pass. Verified: - CircleMaskEffect renders at correct resolution - CNNEffect captured_frame has correct dimensions - No artifacts or half-resolution bugs - Window resize works correctly ## Related Documentation - `doc/MASKING_SYSTEM.md` - Auxiliary texture usage patterns - `doc/EFFECT_WORKFLOW.md` - Effect creation workflow - `src/gpu/effect.h` - MainSequence API reference --- **Decision made:** 2026-02-11 **Implemented by:** Claude Sonnet 4.5 **Status:** Active