diff options
| author | skal <pascal.massimino@gmail.com> | 2026-03-19 20:57:15 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-03-19 20:57:15 +0100 |
| commit | 4c0907bf71150794f7b235f1c2abfab48e728df3 (patch) | |
| tree | 3d0bf7046b93b7eb71085b62f1853e42e067ac73 /doc/archive | |
| parent | fca0f9e7ceaf3cbb70f7f3d1832db019cb757d42 (diff) | |
docs: archive stale/completed docs, compact active refs (-1300 lines)
- Archive WORKSPACE_SYSTEM.md (completed); replace with 36-line operational ref
- Archive SHADER_REUSE_INVESTIGATION.md (implemented Feb 2026)
- Archive GPU_PROCEDURAL_PHASE4.md (completed feature)
- Archive GEOM_BUFFER.md (ideation only, never implemented)
- Archive SPECTRAL_BRUSH_EDITOR.md (v1 DCT approach, superseded by MQ v2)
- Update CLAUDE.md Tier 3 refs; point Audio to SPECTRAL_BRUSH_2.md
- Update TODO.md Task #5 design link to SPECTRAL_BRUSH_2.md
- Update COMPLETED.md archive index
handoff(Claude): doc cleanup done, 30 active docs (was 34), -1300 lines
Diffstat (limited to 'doc/archive')
| -rw-r--r-- | doc/archive/GEOM_BUFFER.md | 229 | ||||
| -rw-r--r-- | doc/archive/GPU_PROCEDURAL_PHASE4.md | 70 | ||||
| -rw-r--r-- | doc/archive/SHADER_REUSE_INVESTIGATION.md | 241 | ||||
| -rw-r--r-- | doc/archive/SPECTRAL_BRUSH_EDITOR.md | 195 | ||||
| -rw-r--r-- | doc/archive/WORKSPACE_SYSTEM.md | 576 |
5 files changed, 1311 insertions, 0 deletions
diff --git a/doc/archive/GEOM_BUFFER.md b/doc/archive/GEOM_BUFFER.md new file mode 100644 index 0000000..0188125 --- /dev/null +++ b/doc/archive/GEOM_BUFFER.md @@ -0,0 +1,229 @@ +# Geometry Buffer Design [IN PROGRESS] + +**Status:** Ideation phase +**Goal:** Efficient G-buffer for deferred rendering in 64k demo + +--- + +## Overview + +Replace direct rendering with geometry buffer accumulation for advanced post-processing and lighting. + +**Target:** 8-10 bytes/pixel, 16-bit precision + +--- + +## Buffer Elements + +### Core Attributes + +| Attribute | Channels | Precision | Source | +|-----------|----------|-----------|--------| +| Albedo (RGB) | 3 | f16 | Material/procedural | +| Roughness | 1 | u8/u16 | PBR material property | +| Metallic | 1 | u8/u16 | PBR material property | +| Normal (XYZ) | 2 | f16 | Octahedral encoding | +| Depth | 1 | f16/f32 | 1/z for precision | +| Object/Material ID | 1 | u16 | Rasterization/SDF | +| Transparency | 1 | u8/u16 | Alpha channel | + +### Optional/Derived + +| Attribute | Storage | Notes | +|-----------|---------|-------| +| Depth gradient | On-demand | Compute from depth (Sobel) | +| Laplacian | On-demand | Second derivative of depth | +| Motion vectors | 2×f16 | Screen-space XY | +| AO | 1×f16 | Ambient occlusion | + +**Key insight:** Depth derivatives cheaper to compute than store (2-4 bytes/pixel saved). + +--- + +## Packing Strategies + +### Traditional Multi-Render-Target (MRT) + +``` +RT0 (RGBA16): Albedo.rgb + Roughness (packed with metallic) +RT1 (RG16): Octahedral normal (2 channels encode XYZ) +RT2 (R32F): 1/z depth (or use hardware depth buffer) +RT3 (RG16): Motion vectors XY +RT4 (R16UI): Object/Material ID +``` + +**Total:** 4-5 render targets = 8-10 bytes/pixel + +### Compute Shader + Storage Buffer (RECOMMENDED) + +**Advantages:** +- Custom bit-packing (not bound to RGBA formats) +- Compute derivatives in-pass (depth gradient, Laplacian) +- Cache-optimized tiling (Morton order) +- No MRT limits (store 20+ attributes) + +**Tradeoffs:** +- No hardware depth/early-Z during G-buffer generation +- Manual atomics if pixel overdraw +- Lose ROPs hardware optimizations + +**Struct Layout:** +```cpp +struct GBufferPixel { + u32 packed_normal; // Octahedral 16+16 + u32 rgba_rough; // RGBA8 + Roughness8 + Metallic8 (26 bits used) + f16 inv_z; // 1/z depth + u16 material_id; // Object/material + // Total: 12 bytes/pixel +}; + +// Compressed variant (8 bytes): +struct CompactGBuffer { + u32 normal_depth; // Oct16 normal + u16 quantized depth + u32 rgba_params; // RGB565 + Rough4 + Metal4 + Flags4 +}; +``` + +**Access Pattern:** +```wgsl +@group(0) @binding(0) var<storage, read_write> g_buffer: array<GBufferPixel>; + +fn write_gbuffer(pixel_id: u32, data: SurfaceData) { + g_buffer[pixel_id].packed_normal = pack_octahedral(data.normal); + g_buffer[pixel_id].rgba_rough = pack_rgba8(data.albedo) | (u32(data.roughness * 255.0) << 24); + g_buffer[pixel_id].inv_z = f16(1.0 / data.depth); + g_buffer[pixel_id].material_id = data.id; +} +``` + +--- + +## Normal Encoding + +**Octahedral mapping** (most efficient for 2-channel storage): +- Encodes unit sphere normal to 2D square +- 16-bit per channel = good precision +- Fast encode/decode (no trig) + +```cpp +vec2 octahedral_encode(vec3 n) { + n /= (abs(n.x) + abs(n.y) + abs(n.z)); + vec2 p = n.z >= 0.0 ? n.xy : (1.0 - abs(n.yx)) * sign(n.xy); + return p * 0.5 + 0.5; // [0, 1] +} + +vec3 octahedral_decode(vec2 p) { + p = p * 2.0 - 1.0; // [-1, 1] + vec3 n = vec3(p.x, p.y, 1.0 - abs(p.x) - abs(p.y)); + float t = max(-n.z, 0.0); + n.x += n.x >= 0.0 ? -t : t; + n.y += n.y >= 0.0 ? -t : t; + return normalize(n); +} +``` + +--- + +## Depth Storage + +**1/z (inverse depth):** +- Better precision distribution (more bits near camera) +- Linear in screen space +- Matches perspective projection + +**Alternatives:** +- Logarithmic depth (even better precision) +- Hardware depth buffer (R32F, free with render targets) + +--- + +## Material Properties + +**Roughness/Metallic are NOT geometry:** +- **Source:** Texture lookups, procedural noise, or constants +- **Not bump-mapping:** Bump/normal maps perturb normals (geometry) +- **PBR properties:** Control light interaction (0=smooth/dielectric, 1=rough/metal) + +**Demoscene approach:** Procedural generation or baked constants (avoid textures). + +--- + +## Post-Processing Derivatives + +**Compute on-demand** (cheaper than storing): + +```wgsl +// Depth gradient (Sobel filter) +fn depth_gradient(uv: vec2f) -> vec2f { + let dx = textureLoad(depth, uv + vec2(1,0)) - textureLoad(depth, uv - vec2(1,0)); + let dy = textureLoad(depth, uv + vec2(0,1)) - textureLoad(depth, uv - vec2(0,1)); + return vec2(dx, dy) * 0.5; +} + +// Laplacian (edge detection) +fn laplacian(uv: vec2f) -> f32 { + let c = textureLoad(depth, uv); + let n = textureLoad(depth, uv + vec2(0,1)); + let s = textureLoad(depth, uv - vec2(0,1)); + let e = textureLoad(depth, uv + vec2(1,0)); + let w = textureLoad(depth, uv - vec2(1,0)); + return (n + s + e + w) - 4.0 * c; +} +``` + +--- + +## Integration with Hybrid Renderer + +**Current:** Hybrid SDF raymarching + rasterized proxy geometry +**Future:** Both write to unified G-buffer + +```cpp +// Rasterization pass +void rasterize_geometry() { + // Vertex shader → fragment shader + // Write to G-buffer (compute or MRT) +} + +// SDF raymarching pass (compute) +void raymarch_sdf() { + // Per-pixel ray march + // Write to same G-buffer at hit points +} + +// Deferred lighting pass +void deferred_lighting() { + // Read G-buffer + // Apply PBR lighting, shadows, etc. +} +``` + +**Atomics handling:** Use depth test or tile-based sorting to avoid conflicts. + +--- + +## Size Budget + +**Target:** 1920×1080 @ 8 bytes/pixel = **16 MB** +**Compressed:** 1920×1080 @ 6 bytes/pixel = **12 MB** + +**Acceptable for 64k demo:** RAM usage OK, not binary size. + +--- + +## Next Steps + +1. Prototype compute shader G-buffer writer +2. Implement octahedral normal encoding +3. Test SDF + raster unified writes +4. Add deferred lighting pass +5. Validate depth derivative quality (gradient/Laplacian) +6. Optimize packing (aim for 6-8 bytes/pixel) + +--- + +## References + +- Octahedral mapping: "Survey of Efficient Representations for Independent Unit Vectors" (Meyer et al.) +- PBR theory: "Physically Based Rendering" (Pharr, Jakob, Humphreys) +- G-buffer design: "Deferred Rendering in Killzone 2" (Valient, 2007) diff --git a/doc/archive/GPU_PROCEDURAL_PHASE4.md b/doc/archive/GPU_PROCEDURAL_PHASE4.md new file mode 100644 index 0000000..4cfc271 --- /dev/null +++ b/doc/archive/GPU_PROCEDURAL_PHASE4.md @@ -0,0 +1,70 @@ +# GPU Procedural Phase 4: Texture Composition + +**Status:** ✅ Complete + +## Implementation + +Multi-input composite shaders with configurable sampler support. + +### API + +```cpp +enum class SamplerType { + LinearClamp, LinearRepeat, NearestClamp, NearestRepeat +}; + +void create_gpu_composite_texture( + const std::string& name, + const std::string& shader_func, + const char* shader_code, + const void* uniform_data, + size_t uniform_size, + int width, int height, + const std::vector<std::string>& input_names, + SamplerType sampler = SamplerType::LinearClamp); +``` + +### Shaders + +**gen_blend.wgsl** - Blend two textures with lerp factor: +- Bindings: output (0), uniform (1), input_a (2), input_b (3), sampler (4) +- Uniform: `{u32 width, height; f32 blend_factor, _pad0}` + +**gen_mask.wgsl** - Multiply textures (masking): +- Bindings: output (0), uniform (1), input_a (2), input_b (3), sampler (4) +- Uniform: `{u32 width, height}` + +### Usage + +```cpp +extern const char* gen_blend_compute_wgsl; + +struct { uint32_t width, height; float blend_factor, _pad0; } uni = {256, 256, 0.5f, 0.0f}; + +tex_mgr.create_gpu_composite_texture( + "blended", "gen_blend", gen_blend_compute_wgsl, + &uni, sizeof(uni), 256, 256, + {"noise_a", "noise_b"}, + SamplerType::LinearClamp); +``` + +### Features + +- **Dynamic bind groups:** N input textures + 1 sampler +- **Lazy sampler creation:** Map-based cache, 4 preset types +- **Multi-stage composition:** Composite of composites supported +- **Guarded with `#if !defined(STRIP_GPU_COMPOSITE)`** + +### Size Impact + +- Code: ~460 lines added +- Compressed: ~830 bytes (2 shaders + dispatch logic) + +### Tests + +`test_gpu_composite.cc`: +- Blend two noise textures +- Mask noise with grid +- Multi-stage composite (composite of composites) + +All 35 tests passing. diff --git a/doc/archive/SHADER_REUSE_INVESTIGATION.md b/doc/archive/SHADER_REUSE_INVESTIGATION.md new file mode 100644 index 0000000..e840126 --- /dev/null +++ b/doc/archive/SHADER_REUSE_INVESTIGATION.md @@ -0,0 +1,241 @@ +# Shader Code Reuse Investigation + +## ✅ Implementation Status + +**Date:** February 13, 2026 +**Solution:** Option 1 - Shared Common Directory +**Status:** IMPLEMENTED + +**Results:** +- Created `src/shaders/` with 20 shared shader files (moved from `common/shaders/` 2026-02-28) +- Eliminated 36 duplicate files across workspaces +- Asset references use `../../src/shaders/...` +- Enhanced asset_packer with filesystem path normalization +- Build passes, all tests pass + +See `doc/FILE_HIERARCHY_CLEANUP_2026-02-13.md` for full details. + +--- + +## Investigation (Historical) + +### Current State + +### Duplication Analysis +- **36 duplicate shader files** between main and test workspaces +- Common files include: math utilities, render helpers, compute shaders, uniforms +- Files are byte-identical duplicates (verified) + +### Current System Architecture +1. **ShaderComposer**: Runtime shader composition via `#include` directives +2. **Asset System**: Shaders loaded from workspace `assets.txt` +3. **Registration**: `InitShaderComposer()` registers snippets with paths like: + - `common_uniforms` + - `math/sdf_shapes`, `math/noise`, `math/common_utils` + - `render/shadows`, `render/scene_query_bvh`, `render/lighting_utils` + +### Duplicate Common Shaders +``` +Common across both workspaces: +- common_uniforms.wgsl +- math/{common_utils, noise, sdf_shapes, sdf_utils}.wgsl +- render/{lighting_utils, scene_query_bvh, scene_query_linear, shadows}.wgsl +- compute/{gen_blend, gen_grid, gen_mask, gen_noise, gen_perlin}.wgsl +- Various effect shaders (passthrough, lighting, ray_box, etc.) +``` + +--- + +## Proposed Approaches + +### Option 1: Shared Common Directory (Original Design) +**Structure:** +``` +/common/ + /shaders/ + /math/ # Shared math utilities + /render/ # Shared rendering helpers + /compute/ # Shared compute shaders + common_uniforms.wgsl + +/workspaces/ + /main/ + /shaders/ # Workspace-specific only + /music/ + /weights/ + /obj/ +``` + +**Pros:** +- Single source of truth for common code +- No duplication +- Clear separation: common vs workspace-specific +- Matches original design doc intent + +**Cons:** +- Breaks workspace isolation (workspaces depend on external directory) +- Harder to version control per-workspace +- Need to update asset packer to handle cross-workspace references +- Complicates workspace portability + +--- + +### Option 2: Symbolic Links +**Structure:** +``` +/workspaces/ + /main/ + /shaders/ + /common@ -> ../../common/shaders/ # Symlink + custom_effect.wgsl +``` + +**Pros:** +- Maintains single source +- Works with existing asset system +- Simple filesystem solution + +**Cons:** +- Windows symlink issues (requires admin or dev mode) +- Git symlink handling varies +- Still breaks workspace isolation +- Can confuse developers + +--- + +### Option 3: Build-Time Copy/Sync +**Structure:** +Workspaces keep duplicates, but sync from canonical source at build time. + +``` +/common/shaders/ # Canonical source +/workspaces/*/shaders/ # Build-synced copies +``` + +**Implementation:** +- CMake script copies common/ → workspaces/ before asset packing +- Or: Pre-commit hook validates consistency + +**Pros:** +- Workspaces remain self-contained +- No runtime dependencies +- Works across all platforms +- Git shows actual files + +**Cons:** +- Easy to forget sync +- Merge conflicts if edited in workspace +- Need tooling to maintain consistency + +--- + +### Option 4: Asset System Extension +**Enhance asset packer to support cross-workspace includes:** + +`workspaces/main/assets.txt`: +``` +SHADER_COMMON_UTILS, NONE, @common/shaders/math/common_utils.wgsl +SHADER_CUSTOM, NONE, shaders/custom_effect.wgsl +``` + +**Pros:** +- Clean at asset definition level +- ShaderComposer unchanged +- Explicit common vs local + +**Cons:** +- Asset packer modification needed +- New syntax to learn +- Breaks workspace portability + +--- + +### Option 5: Status Quo + Documentation +**Keep duplicates, document as intentional.** + +Add `common/shaders/` as reference templates that workspaces copy. + +**Pros:** +- Workspaces fully independent +- Can diverge per-workspace if needed +- No build system changes +- Simple mental model + +**Cons:** +- Ongoing duplication +- Manual sync required +- Disk space (minimal impact) +- Bug fixes need multi-workspace updates + +--- + +## Recommendation Matrix + +| Criteria | Opt 1 | Opt 2 | Opt 3 | Opt 4 | Opt 5 | +|----------|-------|-------|-------|-------|-------| +| No duplication | ✓ | ✓ | ✗ | ✓ | ✗ | +| Workspace isolation | ✗ | ✗ | ✓ | ✗ | ✓ | +| Cross-platform | ✓ | ✗ | ✓ | ✓ | ✓ | +| Low complexity | ✗ | ✓ | ✗ | ✗ | ✓ | +| Easy maintenance | ✓ | ✓ | ✗ | ✓ | ✗ | + +--- + +## Current Implementation Details + +### How Shaders Are Currently Included + +**In WGSL files:** +```wgsl +#include "common_uniforms" +#include "math/sdf_shapes" +#include "render/shadows" +``` + +**In C++ (shaders.cc):** +```cpp +void InitShaderComposer() { + auto& sc = ShaderComposer::Get(); + sc.RegisterSnippet("common_uniforms", ...); + sc.RegisterSnippet("math/sdf_shapes", ...); + sc.RegisterSnippet("render/shadows", ...); +} +``` + +**Asset Registration (assets.txt):** +``` +SHADER_MATH_SDF_SHAPES, NONE, shaders/math/sdf_shapes.wgsl +SHADER_RENDER_SHADOWS, NONE, shaders/render/shadows.wgsl +``` + +### ShaderComposer Flow +1. Assets loaded from workspace `assets.txt` +2. Snippets registered in `InitShaderComposer()` +3. Effects call `Compose()` with dependencies +4. `#include` directives recursively resolved +5. Final shader string assembled + +--- + +## Next Steps + +1. **Decide on approach** based on project priorities: + - Simplicity → Option 5 + - True reuse → Option 1 or 4 + - Compatibility → Option 3 + +2. **If Option 1 chosen:** + - Create `/common/shaders/` with canonical sources + - Update `workspace.cfg` to reference common + - Update asset packer to resolve `../common/` paths + - Update docs + +3. **If Option 3 chosen:** + - Create sync script in `scripts/` + - Add to build process + - Document workflow + +4. **If Option 5 chosen:** + - Create `/common/shaders/` as templates + - Add `doc/SHADER_COMMON.md` explaining pattern + - Accept duplication as intentional diff --git a/doc/archive/SPECTRAL_BRUSH_EDITOR.md b/doc/archive/SPECTRAL_BRUSH_EDITOR.md new file mode 100644 index 0000000..a7d0e3a --- /dev/null +++ b/doc/archive/SPECTRAL_BRUSH_EDITOR.md @@ -0,0 +1,195 @@ +# Spectral Brush Editor (Task #5) + +## Concept + +Replace large `.spec` assets with procedural C++ code (50-100× compression). + +**Before:** 5 KB binary `.spec` file +**After:** ~100 bytes C++ code calling `draw_bezier_curve()` + +**Workflow:** +``` +.wav → Load in editor → Trace with Bezier curves → Export procedural_params.txt + C++ code +``` + +--- + +## Core Primitive: "Spectral Brush" + +### 1. Central Curve (Bezier) +Traces time-frequency path: `{freq_bin, amplitude} = bezier(frame_number)` + +**Example control points:** +```javascript +[ + {frame: 0, freq_hz: 200.0, amplitude: 0.9}, // Attack + {frame: 20, freq_hz: 80.0, amplitude: 0.7}, // Sustain + {frame: 100, freq_hz: 50.0, amplitude: 0.0} // Decay +] +``` + +### 2. Vertical Profile +Shapes "brush stroke" around curve at each frame. + +**Profile Types:** +- **Gaussian**: `exp(-(dist² / σ²))` - Musical tones, bass +- **Decaying Sinusoid**: `exp(-decay * dist) * cos(ω * dist)` - Metallic sounds +- **Noise**: `random(seed, dist) * amplitude` - Hi-hats, cymbals +- **Composite**: Combine multiple profiles (add/subtract/multiply) + +--- + +## File Formats + +### A. `procedural_params.txt` (Human-readable) +```text +METADATA dct_size=512 num_frames=100 sample_rate=32000 + +CURVE bezier + CONTROL_POINT 0 200.0 0.9 + CONTROL_POINT 20 80.0 0.7 + CONTROL_POINT 100 50.0 0.0 + PROFILE gaussian sigma=30.0 +END_CURVE +``` + +### B. C++ Code (Ready to compile) +```cpp +#include "audio/spectral_brush.h" + +void gen_kick_procedural(float* spec, int dct_size, int num_frames) { + const float frames[] = {0.0f, 20.0f, 100.0f}; + const float freqs[] = {200.0f, 80.0f, 50.0f}; + const float amps[] = {0.9f, 0.7f, 0.0f}; + + draw_bezier_curve(spec, dct_size, num_frames, + frames, freqs, amps, 3, + PROFILE_GAUSSIAN, 30.0f); +} +``` + +--- + +## C++ Runtime API + +### Files: `src/audio/spectral_brush.{h,cc}` + +**Key functions:** +```cpp +enum ProfileType { + PROFILE_GAUSSIAN, + PROFILE_DECAYING_SINUSOID, + PROFILE_NOISE +}; + +void draw_bezier_curve(float* spectrogram, int dct_size, int num_frames, + const float* control_frames, + const float* control_freqs_hz, + const float* control_amps, + int n_control_points, + ProfileType profile_type, + float profile_param1, + float profile_param2 = 0.0f); + +float evaluate_bezier_linear(const float* control_frames, + const float* control_values, + int n_points, + float frame); + +float evaluate_profile(ProfileType type, float distance, + float param1, float param2); +``` + +--- + +## Editor UI + +### Technology Stack +- HTML5 Canvas (visualization) +- Web Audio API (playback) +- Pure JavaScript (no dependencies) +- Reuse `dct.js` from existing editor + +### Key Features +- Dual-layer canvas (reference + procedural spectrograms) +- Drag control points to adjust curves +- Real-time spectrogram rendering +- Audio playback (keys 1/2 for procedural/original) +- Undo/Redo (Ctrl+Z, Ctrl+Shift+Z) +- Load .wav/.spec, save params, generate C++ code + +### Keyboard Shortcuts +| Key | Action | +|-----|--------| +| 1 | Play procedural | +| 2 | Play original | +| Space | Play/pause | +| Delete | Remove control point | +| Ctrl+Z | Undo | +| Ctrl+S | Save params | + +--- + +## Implementation Phases + +### Phase 1: C++ Runtime +**Files:** `src/audio/spectral_brush.{h,cc}`, `src/tests/test_spectral_brush.cc` + +**Tasks:** +- Define API (ProfileType, draw_bezier_curve, evaluate_profile) +- Implement linear Bezier interpolation +- Implement Gaussian profile +- Add unit tests +- **Deliverable:** Compiles, tests pass + +### Phase 2: Editor Core +**Files:** `tools/spectral_editor/{index.html, script.js, style.css, dct.js}` + +**Tasks:** +- HTML structure (canvas, controls, file input) +- Bezier curve editor (place/drag/delete control points) +- Dual-layer canvas rendering +- Real-time spectrogram generation +- Audio playback (IDCT → Web Audio API) +- Undo/Redo system +- **Deliverable:** Interactive editor, can trace .wav files + +### Phase 3: File I/O +**Tasks:** +- Load .wav (decode, STFT → spectrogram) +- Load .spec (binary parser) +- Save procedural_params.txt (text format) +- Generate C++ code (template) +- Load procedural_params.txt (re-editing) +- **Deliverable:** Full save/load cycle + +--- + +## Design Decisions + +- **Bezier:** Linear interpolation (Phase 1), cubic later +- **Profiles:** Gaussian only (Phase 1), others later +- **Parameters:** Soft UI limits, no enforced bounds +- **RNG:** Home-brew deterministic (small, repeatable) +- **Code gen:** Single function per sound (generic loader later) + +--- + +## Size Impact + +**Example: Kick drum** + +**Before (Binary):** +- 512 bins × 100 frames × 4 bytes = 200 KB uncompressed +- ~5 KB compressed (zlib) + +**After (Procedural):** +- 4 control points × 3 arrays × 4 floats = ~48 bytes data +- Function call overhead = ~20 bytes +- **Total: ~100 bytes** (50-100× reduction) + +**Trade-off:** Runtime CPU cost, acceptable for 64k demo. + +--- + +*See TODO.md for detailed implementation tasks.* diff --git a/doc/archive/WORKSPACE_SYSTEM.md b/doc/archive/WORKSPACE_SYSTEM.md new file mode 100644 index 0000000..6b4319d --- /dev/null +++ b/doc/archive/WORKSPACE_SYSTEM.md @@ -0,0 +1,576 @@ +# Workspace System (Task #77) [COMPLETED] + +## Status + +**Implemented:** Feb 9, 2026 + +Workspace system is now active. Use `cmake -B build -DDEMO_WORKSPACE=<name>` to select workspace. + +## Overview + +Self-contained demo workspaces for parallel development and clean content separation. + +**Motivation:** Current structure scatters demo content across multiple locations: +- `assets/demo.seq` - Timeline +- `assets/music.track` - Audio +- `assets/final/demo_assets.txt` - Asset list +- `assets/final/music/*.spec` - Audio samples +- `assets/shaders/*.wgsl` - Shaders (some demo-specific, some shared) + +This makes it hard to: +- Work on multiple demos simultaneously +- Understand what files belong to which demo +- Share common resources cleanly +- Onboard new developers + +## Problem Statement + +**Current structure (flat):** +``` +/assets/ + demo.seq # Main demo timeline + music.track # Main demo music + test_demo.seq # Test demo timeline + test_demo.track # Test demo music + /final/ + demo_assets.txt # Main demo assets + /music/*.spec # Audio samples (mixed usage) + /shaders/ + *.wgsl # Mixed: common + demo-specific +``` + +**Issues:** +1. No clear ownership of files +2. Can't easily switch between demos +3. Assets intermingled (demo vs test) +4. Shaders hard to categorize (shared vs demo-specific) +5. Adding new demos requires scattered changes + +## Current Structure (Implemented) + +### Workspace Directory Layout + +``` +/workspaces/ + /main/ # Main production demo + workspace.cfg # Workspace metadata + timeline.seq # Visual effects + music.track # Audio patterns + assets.txt # Asset list + /music/*.spec # Audio samples + /weights/*.bin # CNN binary weights + /obj/*.obj # 3D models + /shaders/ # Workspace-specific shaders only + custom_effect.wgsl + + /test/ # Test/validation demo + workspace.cfg + timeline.seq + music.track + assets.txt + /music/ + /weights/ + /obj/ + /shaders/ + +/common/ # Shared resources + /shaders/ + /math/ # Shared math utilities + common_utils.wgsl + noise.wgsl + sdf_shapes.wgsl + sdf_utils.wgsl + /render/ # Shared rendering helpers + lighting_utils.wgsl + scene_query_bvh.wgsl + scene_query_linear.wgsl + shadows.wgsl + /compute/ # Shared compute shaders + gen_blend.wgsl + gen_grid.wgsl + gen_mask.wgsl + gen_noise.wgsl + gen_perlin.wgsl + common_uniforms.wgsl + lighting.wgsl + passthrough.wgsl + ray_box.wgsl + ray_triangle.wgsl + sdf_primitives.wgsl + skybox.wgsl + +/tools/ + originals/ # Source audio files (.wav, .aif) +``` + +### Workspace Configuration + +**`workspace.cfg` format:** +```ini +[workspace] +name = "Main Demo" +description = "Production 64k demo" +version = "1.0" + +[build] +target = "demo64k" +timeline = "timeline.seq" +music = "music.track" +assets = "assets.txt" +asset_dirs = ["music/", "weights/", "obj/"] +shader_dirs = ["shaders/"] + +[build] +# Output binary name +target = "demo64k" + +# Include paths (relative to workspace root) +timeline = "timeline.seq" +music = "music.track" +assets = "assets.txt" + +# Asset directories +asset_dirs = ["assets/", "../common/audio/"] + +# Shader directories (order matters: workspace-specific first) +shader_dirs = ["shaders/", "../src/shaders/"] + +[options] +# Default resolution +width = 1280 +height = 720 + +# Duration (seconds, -1 = auto-detect) +duration = -1 + +# BPM for timeline +bpm = 120 +``` + +## Architecture + +### Build System Integration + +**CMakeLists.txt changes:** +```cmake +# Select active workspace (default: main) +set(DEMO_WORKSPACE "main" CACHE STRING "Active workspace") + +# Parse workspace config +set(WORKSPACE_DIR "${CMAKE_SOURCE_DIR}/workspaces/${DEMO_WORKSPACE}") +set(WORKSPACE_CFG "${WORKSPACE_DIR}/workspace.cfg") + +# Read config and set variables +parse_workspace_config(${WORKSPACE_CFG} + TIMELINE_PATH + MUSIC_PATH + ASSETS_PATH + ASSET_DIRS + SHADER_DIRS + TARGET_NAME +) + +# Generate assets from workspace +add_custom_command( + OUTPUT ${GEN_ASSETS_H} + COMMAND asset_packer ${WORKSPACE_DIR}/${ASSETS_PATH} ... + DEPENDS ${WORKSPACE_DIR}/${ASSETS_PATH} +) + +# Generate timeline from workspace +add_custom_command( + OUTPUT ${GEN_TIMELINE_CC} + COMMAND seq_compiler ${WORKSPACE_DIR}/${TIMELINE_PATH} ... + DEPENDS ${WORKSPACE_DIR}/${TIMELINE_PATH} +) + +# Add shader include paths from workspace +foreach(SHADER_DIR ${SHADER_DIRS}) + list(APPEND SHADER_INCLUDE_DIRS "${WORKSPACE_DIR}/${SHADER_DIR}") +endforeach() +``` + +**Building specific workspace:** +```bash +# Default (main workspace) +cmake -S . -B build +cmake --build build -j4 + +# Specific workspace +cmake -S . -B build_test -DDEMO_WORKSPACE=test +cmake --build build_test -j4 + +# Experimental workspace +cmake -S . -B build_exp -DDEMO_WORKSPACE=experiments/demo2024_revision +cmake --build build_exp -j4 +``` + +### Asset Packer Changes + +**Support workspace-relative paths:** +```cpp +// asset_packer.cc +void PackerContext::resolve_asset_path(const char* rel_path) { + // Try workspace-local first + std::string workspace_path = workspace_dir + "/" + rel_path; + if (file_exists(workspace_path)) { + return workspace_path; + } + + // Try common assets + std::string common_path = "assets/common/" + rel_path; + if (file_exists(common_path)) { + return common_path; + } + + error("Asset not found: %s", rel_path); +} +``` + +### Shader Composer Changes + +**Support multiple include paths:** +```cpp +// shader_composer.cc +class ShaderComposer { + std::vector<std::string> include_paths_; + + void add_include_path(const char* path) { + include_paths_.push_back(path); + } + + std::string resolve_include(const char* filename) { + for (const auto& base : include_paths_) { + std::string full = base + "/" + filename; + if (file_exists(full)) { + return full; + } + } + error("Shader include not found: %s", filename); + } +}; +``` + +**Shader includes with search paths:** +```wgsl +// workspace-specific shader +#include "custom_uniforms.wgsl" // From workspaces/main/shaders/ +#include "math/common_utils.wgsl" // From src/shaders/ +``` + +### CLI Tool + +**`scripts/workspace.sh` - Workspace management:** +```bash +#!/bin/bash +# workspace.sh - Manage demo workspaces + +case "$1" in + list) + # List all workspaces + ls -1 workspaces/ + ;; + + create) + # Create new workspace from template + NAME=$2 + mkdir -p workspaces/$NAME/{assets,shaders} + cp templates/workspace.cfg workspaces/$NAME/ + echo "Created workspace: $NAME" + ;; + + build) + # Build specific workspace + NAME=$2 + cmake -S . -B build_$NAME -DDEMO_WORKSPACE=$NAME + cmake --build build_$NAME -j4 + ;; + + info) + # Show workspace details + NAME=$2 + cat workspaces/$NAME/workspace.cfg + ;; +esac +``` + +**Usage:** +```bash +./scripts/workspace.sh list +./scripts/workspace.sh create my_demo +./scripts/workspace.sh build main +./scripts/workspace.sh info test +``` + +## Implementation Plan + +### Phase 1: Create Workspace Structure + +**1.1 Create directory tree:** +```bash +mkdir -p workspaces/{main,test}/assets +mkdir -p workspaces/{main,test}/shaders +mkdir -p assets/common/{shaders,audio} +``` + +**1.2 Move existing files:** +```bash +# Main demo +mv assets/demo.seq workspaces/main/timeline.seq +mv assets/music.track workspaces/main/music.track +mv assets/final/demo_assets.txt workspaces/main/assets.txt +mv assets/final/music workspaces/main/assets/ + +# Test demo +mv assets/test_demo.seq workspaces/test/timeline.seq +mv assets/test_demo.track workspaces/test/music.track +cp assets/final/demo_assets.txt workspaces/test/assets.txt # Or create minimal version + +# Common shaders +mv assets/shaders/math assets/common/shaders/ +mv assets/shaders/common_uniforms assets/common/shaders/ +``` + +**1.3 Create workspace configs:** +```bash +# Generate workspace.cfg for main and test +# See format above +``` + +### Phase 2: Update Build System + +**2.1 Add workspace parsing:** +- Create `cmake/ParseWorkspace.cmake` +- Parse INI-style config +- Set CMake variables + +**2.2 Update CMakeLists.txt:** +- Add `DEMO_WORKSPACE` option +- Use workspace paths for assets/timeline/music +- Pass shader include paths to ShaderComposer + +**2.3 Update compiler tools:** +- `asset_packer`: Accept workspace root dir +- `seq_compiler`: Accept workspace root dir +- `tracker_compiler`: Accept workspace root dir + +### Phase 3: Update Code + +**3.1 ShaderComposer:** +- Add multi-path include resolution +- Search workspace shaders first, then common + +**3.2 Asset loading:** +- Update paths to match new structure +- Ensure backward compatibility during transition + +**3.3 Generated code:** +- Verify generated assets.h/timeline.cc still work +- Update include paths if needed + +### Phase 4: Documentation & Tools + +**4.1 Update docs:** +- README.md: Explain workspace structure +- HOWTO.md: Document workspace build commands +- CONTRIBUTING.md: Workspace best practices + +**4.2 Create helper scripts:** +- `scripts/workspace.sh`: Workspace management CLI +- `templates/workspace.cfg`: Template for new workspaces + +**4.3 Update CI:** +- Build both main and test workspaces +- Validate workspace isolation + +### Phase 5: Migration & Validation + +**5.1 Test builds:** +```bash +# Build both workspaces +cmake -S . -B build_main -DDEMO_WORKSPACE=main +cmake --build build_main -j4 + +cmake -S . -B build_test -DDEMO_WORKSPACE=test +cmake --build build_test -j4 + +# Run tests +cd build_main && ctest +cd build_test && ctest +``` + +**5.2 Verify isolation:** +- Modify workspace-specific shader → only that workspace affected +- Modify common shader → both workspaces affected + +**5.3 Update .gitignore:** +``` +/build_*/ +/workspaces/*/generated/ +``` + +## Benefits + +### 1. Clear Ownership +Each workspace is self-contained: +```bash +workspaces/main/ +├── workspace.cfg # Configuration +├── timeline.seq # Timeline +├── music.track # Music +├── assets.txt # Assets +├── assets/ # Local assets +└── shaders/ # Local shaders +``` + +### 2. Parallel Development +Multiple developers can work on different demos without conflicts: +```bash +# Developer A: Main demo +cd workspaces/main +vim timeline.seq + +# Developer B: Experimental demo +cd workspaces/experiments/christmas_demo +vim timeline.seq +``` + +### 3. Easy Switching +```bash +# Build main demo +cmake -B build -DDEMO_WORKSPACE=main +./build/demo64k + +# Build test demo +cmake -B build -DDEMO_WORKSPACE=test +./build/test_demo +``` + +### 4. Clean Sharing +Common resources in one place: +``` +assets/common/ +├── shaders/ +│ ├── math/ # Shared by all +│ └── common_uniforms/ +└── audio/ + └── standard_drums.spec +``` + +### 5. Scalability +Easy to add new demos: +```bash +./scripts/workspace.sh create party2025 +cd workspaces/party2025 +# Start developing... +``` + +## Migration Path + +### Backward Compatibility + +During transition, support both structures: +```cmake +if(EXISTS "${CMAKE_SOURCE_DIR}/workspaces/${DEMO_WORKSPACE}") + # New workspace structure + set(USING_WORKSPACES TRUE) +else() + # Legacy flat structure + set(USING_WORKSPACES FALSE) +endif() +``` + +### Gradual Migration + +1. **Phase 1:** Create workspace structure alongside existing +2. **Phase 2:** Update build system to support both +3. **Phase 3:** Move files to workspaces +4. **Phase 4:** Remove legacy paths +5. **Phase 5:** Update all documentation + +**Timeline:** 1-2 weeks for full migration + +## Trade-offs + +### Pros +- Clear project organization +- Parallel demo development +- Clean resource sharing +- Better onboarding for new devs +- Scales to many demos + +### Cons +- Initial migration effort +- Build system complexity increases +- More directories to navigate +- Learning curve for contributors + +### Alternative Approaches + +**1. Monorepo with subprojects:** +- Separate CMake projects per demo +- More isolated but harder to share code + +**2. Configuration files only:** +- Keep flat structure, use config to select files +- Less clear, harder to understand ownership + +**3. Git branches per demo:** +- Each demo is a branch +- Conflicts when merging shared code + +**Chosen:** Workspace system (best balance) + +## Implementation Effort + +**Estimated time: 12-16 hours** + +- Phase 1: Create structure (2-3 hours) +- Phase 2: Build system (4-5 hours) +- Phase 3: Code updates (3-4 hours) +- Phase 4: Documentation (2-3 hours) +- Phase 5: Validation (1-2 hours) + +**Priority:** Medium (improves workflow, not blocking) + +## Success Criteria + +1. Both `main` and `test` workspaces build successfully +2. Switching workspaces requires only CMake flag change +3. Workspace-specific changes don't affect other workspaces +4. Common shader changes affect all workspaces +5. New workspace creation takes < 5 minutes +6. All tests pass for both workspaces +7. Documentation clear for new contributors + +## Related Files + +**New files:** +- `workspaces/main/workspace.cfg` - Main demo config +- `workspaces/test/workspace.cfg` - Test demo config +- `cmake/ParseWorkspace.cmake` - Config parser +- `scripts/workspace.sh` - Workspace CLI tool +- `templates/workspace.cfg` - New workspace template + +**Modified files:** +- `CMakeLists.txt` - Workspace support +- `tools/asset_packer.cc` - Multi-path resolution +- `src/gpu/shader_composer.cc` - Multi-path includes +- `README.md` - Workspace documentation +- `doc/HOWTO.md` - Build commands +- `doc/CONTRIBUTING.md` - Workspace guidelines + +**Moved files:** +- `assets/demo.seq` → `workspaces/main/timeline.seq` +- `assets/music.track` → `workspaces/main/music.track` +- `assets/final/demo_assets.txt` → `workspaces/main/assets.txt` +- `assets/test_demo.*` → `workspaces/test/` +- `assets/shaders/math/` → `assets/common/shaders/math/` + +## Notes + +- This is a **structural refactor**, not a feature +- No runtime behavior changes +- Enables future scalability +- Makes project more professional +- Good foundation for demoscene releases (multiple demos per repo) |
