// Sequence v2: Explicit node system with DAG effect routing // Replaces implicit framebuffer ping-pong with compile-time optimized nodes #pragma once #include "gpu/gpu.h" #include "gpu/uniform_helper.h" #include "util/mini_math.h" #include #include #include #include class EffectV2; enum class NodeType { U8X4_NORM, // RGBAu8 normalized (0-1) - default Source/Sink F32X4, // RGBA float32 F16X8, // 8-channel float16 DEPTH24, // Depth buffer COMPUTE_F32, // Compute buffer }; struct Node { NodeType type; int width; int height; WGPUTexture texture; WGPUTextureView view; std::vector mip_views; // For multi-target render }; struct UniformsSequenceParams { vec2 resolution; float aspect_ratio; float time; // Per-sequence relative time float beat_time; // Musical beats float beat_phase; // Fractional beat 0.0-1.0 float audio_intensity; float _pad; }; static_assert(sizeof(UniformsSequenceParams) == 32, "UniformsSequenceParams must be 32 bytes for WGSL alignment"); class NodeRegistry { public: NodeRegistry(WGPUDevice device, int default_width, int default_height); ~NodeRegistry(); // Declare new node with explicit type/dimensions void declare_node(const std::string& name, NodeType type, int width, int height); // Declare aliased node (ping-pong optimization) void declare_aliased_node(const std::string& name, const std::string& alias_of); // Retrieve views WGPUTextureView get_view(const std::string& name); std::vector get_output_views(const std::vector& names); // Resize all nodes void resize(int width, int height); // Check if node exists bool has_node(const std::string& name) const; private: WGPUDevice device_; int default_width_; int default_height_; std::map nodes_; std::map aliases_; // name -> backing node name void create_texture(Node& node); }; struct EffectDAGNode { std::shared_ptr effect; std::vector input_nodes; std::vector output_nodes; int execution_order; // Topologically sorted }; class SequenceV2 { public: SequenceV2(const GpuContext& ctx, int width, int height); virtual ~SequenceV2() = default; // Virtual methods (most sequences use defaults) virtual void preprocess(float seq_time, float beat_time, float beat_phase, float audio_intensity); virtual void postprocess(WGPUCommandEncoder encoder); virtual void render_effects(WGPUCommandEncoder encoder); void resize(int width, int height); protected: const GpuContext& ctx_; int width_; int height_; NodeRegistry nodes_; std::vector effect_dag_; UniformsSequenceParams params_; UniformBuffer uniforms_buffer_; };