From 7a383635525c9f9617965f3c79a9f2d6c86550cd Mon Sep 17 00:00:00 2001 From: skal Date: Mon, 16 Feb 2026 11:58:34 +0100 Subject: docs(sequence): update and compact v2 documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documentation Changes: - Rewrote SEQUENCE_v2.md: practical guide focused on actual implementation - Removed design philosophy, added concrete examples - Documented all implemented features and current limitations - Added effect creation templates (standard post-process, 3D with depth) - 130 lines → 222 lines (expanded with examples) - Updated EFFECT_WORKFLOW.md for v2 - Changed from v1 Effect/PostProcessEffect to EffectV2 - Updated all steps for v2 workflow (6 steps instead of 8) - Added complete templates with proper v2 signatures - Documented common issues and solutions - Removed v1-specific content - Archived v1 documentation - Moved doc/SEQUENCE.md → doc/archive/SEQUENCE_V1.md - V1 system removed, documentation preserved for reference Content Focus: - Quick start examples (simple chain, multi-output, ping-pong) - Timeline syntax reference with REQUIRED priority modifiers - Architecture overview (SequenceV2, EffectV2, Node system) - Compiler features (DAG validation, topological sort, ping-pong detection) - Practical templates (copy-paste ready) - Common issues section (build errors, runtime errors) Status Documentation: - ✅ Implemented: DAG validation, node aliasing, 7 effects ported - ❌ Missing: Flatten mode, BPM handling, GetDemoDuration calculation - TODO: Port remaining effects, implement flatten, update HTML editor Co-Authored-By: Claude Sonnet 4.5 --- doc/EFFECT_WORKFLOW.md | 356 +++++++++++++++++++++++---------------------- doc/SEQUENCE.md | 220 ---------------------------- doc/SEQUENCE_v2.md | 315 +++++++++++++++++++++++++-------------- doc/archive/SEQUENCE_V1.md | 220 ++++++++++++++++++++++++++++ 4 files changed, 605 insertions(+), 506 deletions(-) delete mode 100644 doc/SEQUENCE.md create mode 100644 doc/archive/SEQUENCE_V1.md diff --git a/doc/EFFECT_WORKFLOW.md b/doc/EFFECT_WORKFLOW.md index 57cf904..bdec2b6 100644 --- a/doc/EFFECT_WORKFLOW.md +++ b/doc/EFFECT_WORKFLOW.md @@ -1,248 +1,256 @@ -# Effect Creation Workflow +# Effect Creation Workflow (v2) **Target Audience:** AI coding agents and developers -Automated checklist for adding new visual effects to the demo. +Checklist for adding visual effects using Sequence v2 system. --- ## Quick Reference -**For ShaderToy conversions:** Use `tools/shadertoy/convert_shadertoy.py` then follow steps 3-8 below. - -**For SDF/raymarching effects:** See `doc/SDF_EFFECT_GUIDE.md` for streamlined workflow using SDFEffect base class. - -**For custom effects:** Follow all steps 1-8. +**ShaderToy:** `tools/shadertoy/convert_shadertoy.py` then follow steps below +**SDF/Raymarching:** See `doc/SDF_EFFECT_GUIDE.md` +**Custom v2 effects:** Follow all steps 1-6 --- -## Step-by-Step Workflow +## Workflow ### 1. Create Effect Files -**Description:** Each visual effect must have its own dedicated header (`.h`) and implementation (`.cc`) file pair. +**Files** (v2 naming): +- Header: `src/effects/_effect_v2.h` +- Implementation: `src/effects/_effect_v2.cc` +- Shader: `workspaces/main/shaders/_v2.wgsl` -**Location:** -- Header: `src/effects/_effect.h` -- Implementation: `src/effects/_effect.cc` -- Shader: `workspaces/main/shaders/.wgsl` +**Class name**: `EffectV2` (e.g., `TunnelEffectV2`) -**Naming Convention:** -- Class name: `Effect` (e.g., `TunnelEffect`, `PlasmaEffect`) -- Files: `_effect.*` (snake_case) +**Base class**: `EffectV2` (all effects) -**Base Class:** -- Post-process effects: inherit from `PostProcessEffect` -- Scene effects: inherit from `Effect` - -**Render Signature:** +**Constructor**: ```cpp -void render(WGPURenderPassEncoder pass, - const CommonPostProcessUniforms& uniforms) override; +MyEffectV2(const GpuContext& ctx, + const std::vector& inputs, + const std::vector& outputs); ``` -**Uniforms Available:** +**Required methods**: ```cpp -uniforms.time; // Physical seconds (constant speed) -uniforms.beat_time; // Musical beats (bar synchronization) -uniforms.beat_phase; // Fractional beat 0.0-1.0 (smooth oscillation) -uniforms.audio_intensity; // Audio peak for beat sync -uniforms.resolution; // Screen dimensions -uniforms.aspect_ratio; // Width/height ratio +void render(WGPUCommandEncoder encoder, + const UniformsSequenceParams& params, + NodeRegistry& nodes) override; + +// Optional: for effects needing temp nodes (depth buffers, intermediate textures) +void declare_nodes(NodeRegistry& registry) override; ``` -**Template:** See `tools/shadertoy/template.*` or use `convert_shadertoy.py` +**Uniforms**: +```cpp +params.time; // Physical seconds +params.beat_time; // Musical beats +params.beat_phase; // Fractional beat 0.0-1.0 +params.audio_intensity; // Audio peak +params.resolution; // vec2(width, height) +params.aspect_ratio; // width/height +``` ### 2. Add Shader to Assets -**File:** `workspaces/main/assets.txt` - -**Format:** -``` -SHADER_, NONE, shaders/.wgsl, "Effect description" -``` +**File**: `workspaces/main/assets.txt` -**Example:** ``` -SHADER_TUNNEL, NONE, shaders/tunnel.wgsl, "Tunnel effect shader" +SHADER_, NONE, shaders/_v2.wgsl, "Description" ``` -**Asset ID:** Will be `AssetId::ASSET_SHADER_` in C++ +Asset ID: `AssetId::ASSET_SHADER_` ### 3. Add to CMakeLists.txt -**File:** `CMakeLists.txt` - -**Action:** Add `src/effects/_effect.cc` to **BOTH** GPU_SOURCES sections: -- Headless mode section (around line 141-167) -- Normal mode section (around line 171-197) - -**Location:** After similar effects (post-process with post-process, scene with scene) +**File**: `CMakeLists.txt` -**Example:** -```cmake -# In headless section (line ~152): - src/effects/solarize_effect.cc - src/effects/tunnel_effect.cc # <-- Add here - src/effects/chroma_aberration_effect.cc - -# In normal section (line ~183): - src/effects/solarize_effect.cc - src/effects/tunnel.cc # <-- Add here - src/effects/chroma_aberration_effect.cc -``` +Add `src/effects/_effect_v2.cc` to **BOTH** GPU_SOURCES sections: +- Headless mode (around line 141-167) +- Normal mode (around line 171-197) ### 4. Include in demo_effects.h -**File:** `src/gpu/demo_effects.h` +**File**: `src/gpu/demo_effects.h` -**Action:** `src/gpu/demo_effects.h` now acts as a central include file. Add a single include directive for your new effect's header: ```cpp -#include "effects/_effect.h" +#include "effects/_effect_v2.h" ``` -**Location:** Alphabetically with other effect includes - ### 5. Add to Timeline -**File:** `workspaces/main/timeline.seq` +**File**: `workspaces/main/timeline_v2.seq` -**Format:** ``` -SEQUENCE - EFFECT <+|=|-> Effect [params...] +SEQUENCE "name" + EFFECT + MyEffectV2 source -> sink 0.0 4.0 ``` -**Priority Modifiers (REQUIRED):** -- `+` : Increment priority -- `=` : Same priority as previous effect -- `-` : Decrement priority (for backgrounds) +**Priority modifiers** (REQUIRED): `+` (increment), `=` (same), `-` (decrement) -**Example:** -``` -SEQUENCE 0.0 0 - EFFECT + TunnelEffect 0.0 10.0 -``` +### 6. Regenerate and Build -**Common Mistake:** Missing priority modifier (`+`, `=`, `-`) after EFFECT keyword +```bash +# Regenerate timeline.cc +python3 tools/seq_compiler_v2.py workspaces/main/timeline_v2.seq \ + --output src/generated/timeline.cc -### 6. Update Tests +# Build +cmake --build build -j4 -**File:** `src/tests/gpu/test_demo_effects.cc` +# Test +./build/demo64k +``` + +--- -**Action:** Add effect to appropriate list: +## Templates + +### Standard Post-Process Effect -**Post-Process Effects (lines 80-93):** ```cpp -{"TunnelEffect", std::make_shared(fixture.ctx())}, +// my_effect_v2.h +#pragma once +#include "gpu/effect_v2.h" +#include "gpu/uniform_helper.h" + +class MyEffectV2 : public EffectV2 { + public: + MyEffectV2(const GpuContext& ctx, + const std::vector& inputs, + const std::vector& outputs); + ~MyEffectV2() override; + + void render(WGPUCommandEncoder encoder, + const UniformsSequenceParams& params, + NodeRegistry& nodes) override; + + private: + WGPURenderPipeline pipeline_; + WGPUBindGroup bind_group_; + UniformBuffer uniforms_buffer_; +}; ``` -**Scene Effects (lines 125-137):** ```cpp -{"TunnelEffect", std::make_shared(fixture.ctx())}, +// my_effect_v2.cc +#include "effects/my_effect_v2.h" +#include "gpu/post_process_helper.h" +#include "gpu/shaders.h" + +MyEffectV2::MyEffectV2(const GpuContext& ctx, + const std::vector& inputs, + const std::vector& outputs) + : EffectV2(ctx, inputs, outputs), pipeline_(nullptr), bind_group_(nullptr) { + uniforms_buffer_.init(ctx_.device); + pipeline_ = create_post_process_pipeline(ctx_.device, + WGPUTextureFormat_RGBA8Unorm, + my_shader_v2_wgsl); +} + +MyEffectV2::~MyEffectV2() { + if (bind_group_) wgpuBindGroupRelease(bind_group_); + if (pipeline_) wgpuRenderPipelineRelease(pipeline_); +} + +void MyEffectV2::render(WGPUCommandEncoder encoder, + const UniformsSequenceParams& params, + NodeRegistry& nodes) { + WGPUTextureView input_view = nodes.get_view(input_nodes_[0]); + WGPUTextureView output_view = nodes.get_view(output_nodes_[0]); + + uniforms_buffer_.update(ctx_.queue, params); + pp_update_bind_group(ctx_.device, pipeline_, &bind_group_, input_view, + uniforms_buffer_.get(), {nullptr, 0}); + + WGPURenderPassColorAttachment color_attachment = { + .view = output_view, +#if !defined(DEMO_CROSS_COMPILE_WIN32) + .depthSlice = WGPU_DEPTH_SLICE_UNDEFINED, +#endif + .loadOp = WGPULoadOp_Clear, + .storeOp = WGPUStoreOp_Store, + .clearValue = {0.0, 0.0, 0.0, 1.0} + }; + + WGPURenderPassDescriptor pass_desc = { + .colorAttachmentCount = 1, + .colorAttachments = &color_attachment + }; + + WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &pass_desc); + wgpuRenderPassEncoderSetPipeline(pass, pipeline_); + wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr); + wgpuRenderPassEncoderDraw(pass, 3, 1, 0, 0); // Fullscreen triangle + wgpuRenderPassEncoderEnd(pass); + wgpuRenderPassEncoderRelease(pass); +} ``` -**3D Effects:** If requires Renderer3D, add to `requires_3d` check (line 148-151) - -### 7. Build and Test - -```bash -# Full build -cmake --build build -j4 - -# Run effect tests -cmake -S . -B build -DDEMO_BUILD_TESTS=ON -cmake --build build -j4 --target test_demo_effects -cd build && ./test_demo_effects +### 3D Effect with Depth -# Run all tests -cd build && ctest +```cpp +class My3DEffectV2 : public EffectV2 { + std::string depth_node_; + + My3DEffectV2(const GpuContext& ctx, ...) + : EffectV2(ctx, inputs, outputs), + depth_node_(outputs[0] + "_depth") {} + + void declare_nodes(NodeRegistry& registry) override { + registry.declare_node(depth_node_, NodeType::DEPTH24, -1, -1); + } + + void render(WGPUCommandEncoder encoder, + const UniformsSequenceParams& params, + NodeRegistry& nodes) override { + WGPUTextureView color_view = nodes.get_view(output_nodes_[0]); + WGPUTextureView depth_view = nodes.get_view(depth_node_); + + WGPURenderPassDepthStencilAttachment depth_attachment = { + .view = depth_view, + .depthLoadOp = WGPULoadOp_Clear, + .depthStoreOp = WGPUStoreOp_Discard, + .depthClearValue = 1.0f + }; + + WGPURenderPassDescriptor pass_desc = { + .colorAttachmentCount = 1, + .colorAttachments = &color_attachment, + .depthStencilAttachment = &depth_attachment + }; + // ... render 3D scene + } +}; ``` -### 8. Verify - -**Checklist:** -- [ ] Effect compiles without errors -- [ ] Effect appears in timeline -- [ ] test_demo_effects passes -- [ ] Effect renders correctly: `./build/demo64k` -- [ ] No shader compilation errors -- [ ] Follows naming conventions - --- ## Common Issues -### Build Error: "no member named 'ASSET_..._SHADER'" - -**Cause:** Shader not in assets.txt or wrong asset ID name - -**Fix:** -1. Check `workspaces/main/assets.txt` has shader entry -2. Asset ID is `ASSET_` + uppercase entry name (e.g., `SHADER_TUNNEL` → `ASSET_SHADER_TUNNEL`) - -### Build Error: "undefined symbol for architecture" - -**Cause:** Effect not in CMakeLists.txt GPU_SOURCES +**Build Error: "no member named 'ASSET_..._SHADER'"** +- Shader not in `assets.txt` or wrong name +- Asset ID is `ASSET_` + uppercase entry name -**Fix:** Add `.cc` file to BOTH sections (headless and normal mode) +**Build Error: "undefined symbol"** +- Effect not in CMakeLists.txt GPU_SOURCES +- Must add to BOTH sections (headless + normal) -### Timeline Parse Error: "Expected '+', '=', or '-'" - -**Cause:** Missing priority modifier after EFFECT keyword - -**Fix:** Use `EFFECT +`, `EFFECT =`, or `EFFECT -` (never just `EFFECT`) - -### Test Failure: Effect not in test list - -**Cause:** Effect not added to test_demo_effects.cc - -**Fix:** Add to `post_process_effects` or `scene_effects` list - ---- +**Runtime Error: "Node not found"** +- Forgot `declare_nodes()` for temp nodes +- `init_effect_nodes()` not called (check generated timeline.cc) -## Automation Script Example - -```bash -#!/bin/bash -# Example automation for AI agents - -EFFECT_NAME="$1" # CamelCase (e.g., "Tunnel") -SNAKE_NAME=$(echo "$EFFECT_NAME" | sed 's/\([A-Z]\)/_\L\1/g' | sed 's/^_//') -UPPER_NAME=$(echo "$SNAKE_NAME" | tr '[:lower:]' '[:upper:]') - -echo "Creating effect: $EFFECT_NAME" -echo " Snake case: $SNAKE_NAME" -echo " Upper case: $UPPER_NAME" - -# 1. Generate files (if using ShaderToy) -# ./tools/shadertoy/convert_shadertoy.py shader.txt "$EFFECT_NAME" - -# 2. Add to assets.txt -echo "SHADER_${UPPER_NAME}, NONE, shaders/${SNAKE_NAME}.wgsl, \"${EFFECT_NAME} effect\"" \ - >> workspaces/main/assets.txt - -# 3. Add to CMakeLists.txt (both sections) -# Use Edit tool to add to both GPU_SOURCES sections - -# 4. Add include to demo_effects.h -# Use Edit tool to add #include line - -# 5. Add to timeline.seq -# Use Edit tool to add EFFECT line with priority modifier - -# 6. Add to test file -# Use Edit tool to add to appropriate test list - -# 7. Build -cmake --build build -j4 -``` +**Runtime Error: "invalid bind group"** +- Pipeline format doesn't match framebuffer (use RGBA8Unorm) +- Missing texture view or null resource --- ## See Also -- `tools/shadertoy/README.md` - ShaderToy conversion guide -- `doc/SEQUENCE.md` - Timeline format documentation -- `doc/CONTRIBUTING.md` - General contribution guidelines -- `src/effects/` - Existing effect examples +- `doc/SEQUENCE_v2.md` - Timeline syntax and architecture +- `tools/seq_compiler_v2.py` - Compiler implementation +- `src/effects/*_v2.{h,cc}` - Example effects diff --git a/doc/SEQUENCE.md b/doc/SEQUENCE.md deleted file mode 100644 index 03d0c45..0000000 --- a/doc/SEQUENCE.md +++ /dev/null @@ -1,220 +0,0 @@ -# Sequence System Documentation - -This document describes the `.seq` file format used to define demo timelines. - -## Overview - -Sequence files (`.seq`) define the timeline and layering of visual effects. They are compiled by `seq_compiler` into C++ code at build time. - -**Locations:** -- Main demo: `workspaces/main/timeline.seq` -- Test demo: `workspaces/test/timeline.seq` -- Compiler: `tools/seq_compiler.cc` -- Generated output: `src/generated/timeline.cc` - ---- - -## Syntax Reference - -### BPM Declaration -``` -# BPM 120 -``` -Specifies beats per minute. Required. Used to convert beats to physical seconds at runtime. - -### END_DEMO Directive -``` -END_DEMO