From 7041babc9e5333d01191f3eb80fd711bd26cd4f7 Mon Sep 17 00:00:00 2001 From: skal Date: Tue, 17 Feb 2026 08:46:01 +0100 Subject: feat: add time-based effect activation with auto-passthrough Effects now accept start/end time parameters and automatically passthrough when inactive. Implements buffer chain integrity via compile-time validation. - Effect base class: dispatch_render() checks time bounds, auto-passthroughs 1:1 input/output effects outside [start, end] interval - seq_compiler.py: validates producer/consumer lifespan constraints for multi-output effects, adds --validate flag, always validates before codegen - Updated all 9 effect classes and test fixtures to pass start/end times - check_all.sh: includes timeline validation step - Tests: 34/34 passing, demo runs successfully Co-Authored-By: Claude Sonnet 4.5 --- src/tests/gpu/test_demo_effects.cc | 18 +++++++++--------- src/tests/gpu/test_effect_base.cc | 8 +++++--- src/tests/gpu/test_sequence.cc | 6 ++++-- src/tests/gpu/test_sequence_e2e.cc | 4 ++-- 4 files changed, 20 insertions(+), 16 deletions(-) (limited to 'src/tests/gpu') diff --git a/src/tests/gpu/test_demo_effects.cc b/src/tests/gpu/test_demo_effects.cc index 7f9d3da..f193c76 100644 --- a/src/tests/gpu/test_demo_effects.cc +++ b/src/tests/gpu/test_demo_effects.cc @@ -39,31 +39,31 @@ static void test_effects() { std::vector>> effects = { {"Passthrough", std::make_shared( fixture.ctx(), std::vector{"source"}, - std::vector{"sink"})}, + std::vector{"sink"}, 0.0f, 1000.0f)}, {"GaussianBlur", std::make_shared( fixture.ctx(), std::vector{"source"}, - std::vector{"sink"})}, + std::vector{"sink"}, 0.0f, 1000.0f)}, {"Placeholder", std::make_shared( fixture.ctx(), std::vector{"source"}, - std::vector{"sink"})}, + std::vector{"sink"}, 0.0f, 1000.0f)}, {"Heptagon", std::make_shared( fixture.ctx(), std::vector{"source"}, - std::vector{"sink"})}, + std::vector{"sink"}, 0.0f, 1000.0f)}, {"Particles", std::make_shared( fixture.ctx(), std::vector{"source"}, - std::vector{"sink"})}, + std::vector{"sink"}, 0.0f, 1000.0f)}, {"RotatingCube", std::make_shared( fixture.ctx(), std::vector{"source"}, - std::vector{"sink"})}, + std::vector{"sink"}, 0.0f, 1000.0f)}, {"Hybrid3D", std::make_shared( fixture.ctx(), std::vector{"source"}, - std::vector{"sink"})}, + std::vector{"sink"}, 0.0f, 1000.0f)}, {"Flash", std::make_shared(fixture.ctx(), std::vector{"source"}, - std::vector{"sink"})}, + std::vector{"sink"}, 0.0f, 1000.0f)}, {"PeakMeter", std::make_shared( fixture.ctx(), std::vector{"source"}, - std::vector{"sink"})}, + std::vector{"sink"}, 0.0f, 1000.0f)}, }; int passed = 0; diff --git a/src/tests/gpu/test_effect_base.cc b/src/tests/gpu/test_effect_base.cc index f46a4ef..29d3348 100644 --- a/src/tests/gpu/test_effect_base.cc +++ b/src/tests/gpu/test_effect_base.cc @@ -83,7 +83,7 @@ static void test_effect_construction() { // Create Passthrough (simple effect) auto effect = std::make_shared( fixture.ctx(), std::vector{"source"}, - std::vector{"sink"}); + std::vector{"sink"}, 0.0f, 1000.0f); assert(effect != nullptr && "Effect should be constructed"); @@ -106,7 +106,8 @@ static void test_effect_in_sequence() { TestSequence(const GpuContext& ctx, int w, int h) : Sequence(ctx, w, h) { auto effect = std::make_shared(ctx, std::vector{"source"}, - std::vector{"sink"}); + std::vector{"sink"}, 0.0f, + 1000.0f); effect_dag_.push_back({effect, {"source"}, {"sink"}, 0}); init_effect_nodes(); @@ -138,7 +139,8 @@ static void test_sequence_render() { TestSequence(const GpuContext& ctx, int w, int h) : Sequence(ctx, w, h) { auto effect = std::make_shared(ctx, std::vector{"source"}, - std::vector{"sink"}); + std::vector{"sink"}, 0.0f, + 1000.0f); effect_dag_.push_back({effect, {"source"}, {"sink"}, 0}); init_effect_nodes(); diff --git a/src/tests/gpu/test_sequence.cc b/src/tests/gpu/test_sequence.cc index fa6bd5e..8e27efb 100644 --- a/src/tests/gpu/test_sequence.cc +++ b/src/tests/gpu/test_sequence.cc @@ -11,8 +11,10 @@ class TestEffect : public Effect { public: TestEffect(const GpuContext& ctx, const std::vector& inputs, - const std::vector& outputs) - : Effect(ctx, inputs, outputs), render_called_(false) { + const std::vector& outputs, float start_time = 0.0f, + float end_time = 1000.0f) + : Effect(ctx, inputs, outputs, start_time, end_time), + render_called_(false) { } void render(WGPUCommandEncoder encoder, const UniformsSequenceParams& params, diff --git a/src/tests/gpu/test_sequence_e2e.cc b/src/tests/gpu/test_sequence_e2e.cc index ed8920a..5d59e0d 100644 --- a/src/tests/gpu/test_sequence_e2e.cc +++ b/src/tests/gpu/test_sequence_e2e.cc @@ -23,13 +23,13 @@ class SimpleTestSequence : public Sequence { // Effect DAG construction (2 effects: source->temp->sink) effect_dag_.push_back({.effect = std::make_shared( ctx, std::vector{"source"}, - std::vector{"temp"}), + std::vector{"temp"}, 0.0f, 1000.0f), .input_nodes = {"source"}, .output_nodes = {"temp"}, .execution_order = 0}); effect_dag_.push_back({.effect = std::make_shared( ctx, std::vector{"temp"}, - std::vector{"sink"}), + std::vector{"sink"}, 0.0f, 1000.0f), .input_nodes = {"temp"}, .output_nodes = {"sink"}, .execution_order = 1}); -- cgit v1.2.3