# Auxiliary Texture Initialization **Technical decision: Effect initialization order (resize → init)** --- ## Problem Auxiliary textures created at wrong resolution (1280×720 defaults instead of actual window size). **Root Cause:** `init()` called before `resize()` in MainSequence. Effects registered textures using default dimensions. ```cpp // BEFORE (effect.cc:180-181) entry.seq->init(this); // Uses width_/height_ = 1280×720 entry.seq->resize(width, height); // Too late - textures already created ``` **Affected:** - CircleMaskEffect (circle_mask texture) - CNNEffect (captured_frame texture) - RotatingCubeEffect (consumer, hardcoded resolution in uniforms) --- ## Solution: Reorder init/resize ✅ Call `resize()` before `init()` to set dimensions first. ```cpp // AFTER (effect.cc:179-180) entry.seq->resize(width, height); // Set dimensions FIRST entry.seq->init(this); // Then init with correct dimensions ``` **Rejected Alternative:** Lazy initialization (ensure_texture() guards) - complexity cascade to consumers. --- ## Implementation ### 1. MainSequence Order Swap **File:** `src/gpu/effect.cc` Lines 179-180 and 189-190: Call `resize()` before `init()`. ### 2. Auxiliary Texture Effects Register textures in `init()` using width_/height_ (now valid): ```cpp void MyEffect::init(MainSequence* demo) { demo_ = demo; demo_->register_auxiliary_texture("my_texture", width_, height_); // Create pipelines/bind groups... } ``` Handle resize with early returns: ```cpp void MyEffect::resize(int width, int height) { if (width == width_ && height == height_) return; Effect::resize(width, height); if (!demo_) return; demo_->resize_auxiliary_texture("my_texture", width, height); // Recreate bind groups... } ``` ### 3. Effects with Renderer3D Add `initialized_` flag to guard resize(): ```cpp // Header bool initialized_ = false; // init() renderer_.init(ctx_.device, ctx_.queue, ctx_.format); renderer_.resize(width_, height_); initialized_ = true; // resize() if (!initialized_) return; // Don't resize uninitialized renderer renderer_.resize(width_, height_); ``` **Why flag?** `ctx_.device` exists before init() but Renderer3D not initialized yet. **Applied to:** FlashCubeEffect, Hybrid3DEffect ### 4. Hardcoded Resolutions **RotatingCubeEffect:** Fixed hardcoded `vec2(1280.0f, 720.0f)` → `u.resolution` **Audit Results:** No other hardcoded resolutions in effects. Defaults in effect.cc:161-162 are test-only. --- ## Guidelines ### Creating Auxiliary Textures ```cpp void MyEffect::init(MainSequence* demo) { demo_ = demo; demo_->register_auxiliary_texture("my_texture", width_, height_); // width_/height_ valid (resize() called before init()) } ``` ### Consuming Auxiliary Textures ```cpp void MyEffect::init(MainSequence* demo) { demo_ = demo; WGPUTextureView view = demo_->get_auxiliary_view("circle_mask"); // Producer effects initialized before consumers (timeline order) } ``` ### Using Resolutions **Always use `u.resolution` from CommonPostProcessUniforms, never hardcode dimensions.** --- ## Testing All 36 tests pass. Verified: - Auxiliary textures at correct resolution - Renderer3D effects don't crash on resize-before-init - No hardcoded resolution artifacts - Window resize works correctly --- ## Related - `doc/MASKING_SYSTEM.md` - Auxiliary texture patterns - `doc/EFFECT_WORKFLOW.md` - Effect creation workflow - `src/gpu/effect.h` - MainSequence API --- **Decision:** 2026-02-11 | **Status:** Active | **By:** Claude Sonnet 4.5