// Test file for Sequence v2 system // Phase 1: Foundation tests (NodeRegistry, Sequence base class) #include "gpu/effect.h" #include "gpu/sequence.h" #include "tests/common/webgpu_test_fixture.h" #include #include // Simple test effect for DAG execution class TestEffect : public Effect { public: TestEffect(const GpuContext& ctx, const std::vector& inputs, const std::vector& outputs) : Effect(ctx, inputs, outputs), render_called_(false) { } void render(WGPUCommandEncoder encoder, const UniformsSequenceParams& params, NodeRegistry& nodes) override { (void)encoder; (void)params; (void)nodes; render_called_ = true; } bool was_render_called() const { return render_called_; } private: bool render_called_; }; // Test: NodeRegistry basic allocation void test_node_registry_basic() { WebGPUTestFixture fixture; if (!fixture.init()) { fprintf(stderr, "Skipping test_node_registry_basic (no GPU)\n"); return; } NodeRegistry registry(fixture.ctx().device, 1280, 720); // Declare node registry.declare_node("test_node", NodeType::U8X4_NORM, 1280, 720); // Verify node exists assert(registry.has_node("test_node")); // Get view (should not crash) WGPUTextureView view = registry.get_view("test_node"); assert(view != nullptr); printf("PASS: NodeRegistry basic allocation\n"); } // Test: NodeRegistry aliased nodes (ping-pong optimization) void test_node_registry_aliased() { WebGPUTestFixture fixture; if (!fixture.init()) { fprintf(stderr, "Skipping test_node_registry_aliased (no GPU)\n"); return; } NodeRegistry registry(fixture.ctx().device, 1280, 720); // Declare backing node registry.declare_node("frame_a", NodeType::U8X4_NORM, 1280, 720); // Declare aliased node registry.declare_aliased_node("frame_b", "frame_a"); // Both should resolve to same view WGPUTextureView view_a = registry.get_view("frame_a"); WGPUTextureView view_b = registry.get_view("frame_b"); assert(view_a == view_b); printf("PASS: NodeRegistry aliased nodes\n"); } // Test: NodeRegistry multi-output views void test_node_registry_multi_output() { WebGPUTestFixture fixture; if (!fixture.init()) { fprintf(stderr, "Skipping test_node_registry_multi_output (no GPU)\n"); return; } NodeRegistry registry(fixture.ctx().device, 1280, 720); // Declare multiple nodes registry.declare_node("output1", NodeType::U8X4_NORM, 1280, 720); registry.declare_node("output2", NodeType::F32X4, 1280, 720); // Get multiple views std::vector names = {"output1", "output2"}; std::vector views = registry.get_output_views(names); assert(views.size() == 2); assert(views[0] != nullptr); assert(views[1] != nullptr); printf("PASS: NodeRegistry multi-output views\n"); } // Test: Sequence default preprocess void test_sequence_v2_preprocess() { WebGPUTestFixture fixture; if (!fixture.init()) { fprintf(stderr, "Skipping test_sequence_v2_preprocess (no GPU)\n"); return; } Sequence seq(fixture.ctx(), 1280, 720); // Call preprocess with test values seq.preprocess(1.0f, 4.0f, 0.5f, 0.8f); // No crash = success (params updated internally) printf("PASS: Sequence preprocess\n"); } // Test: Sequence DAG execution void test_sequence_v2_dag_execution() { WebGPUTestFixture fixture; if (!fixture.init()) { fprintf(stderr, "Skipping test_sequence_v2_dag_execution (no GPU)\n"); return; } // Create sequence class TestSequence : public Sequence { public: TestSequence(const GpuContext& ctx) : Sequence(ctx, 1280, 720), effect1_(std::make_shared( ctx, std::vector{"source"}, std::vector{"temp"})), effect2_(std::make_shared( ctx, std::vector{"temp"}, std::vector{"sink"})) { // Build DAG (2 effects in sequence) effect_dag_.push_back({effect1_, {"source"}, {"temp"}, 0}); effect_dag_.push_back({effect2_, {"temp"}, {"sink"}, 1}); } std::shared_ptr effect1_; std::shared_ptr effect2_; }; TestSequence seq(fixture.ctx()); // Create command encoder WGPUCommandEncoderDescriptor enc_desc = {}; WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(fixture.ctx().device, &enc_desc); // Execute DAG seq.render_effects(encoder); // Verify both effects called assert(seq.effect1_->was_render_called()); assert(seq.effect2_->was_render_called()); // Cleanup WGPUCommandBuffer cmd = wgpuCommandEncoderFinish(encoder, nullptr); wgpuCommandBufferRelease(cmd); wgpuCommandEncoderRelease(encoder); printf("PASS: Sequence DAG execution\n"); } int main() { printf("Running Sequence v2 tests...\n"); test_node_registry_basic(); test_node_registry_aliased(); test_node_registry_multi_output(); test_sequence_v2_preprocess(); test_sequence_v2_dag_execution(); printf("All Sequence v2 tests passed!\n"); return 0; }