// Sequence: DAG-based effect routing with ping-pong optimization #ifndef SEQUENCE_H #define SEQUENCE_H #pragma once #include "gpu/gpu.h" #include "gpu/uniform_helper.h" #include "util/mini_math.h" #include #include #include #include class Effect; enum class NodeType { U8X4_NORM, // RGBAu8 (default Source/Sink) F32X4, F16X8, DEPTH24, COMPUTE_F32, }; 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(); void declare_node(const std::string& name, NodeType type, int width, int height); void declare_aliased_node(const std::string& name, const std::string& alias_of); WGPUTextureView get_view(const std::string& name); std::vector get_output_views(const std::vector& names); WGPUTexture get_texture(const std::string& name); void resize(int width, int height); bool has_node(const std::string& name) const; void set_external_view(const std::string& name, WGPUTextureView view); private: WGPUDevice device_; int default_width_; int default_height_; std::map nodes_; std::map aliases_; void create_texture(Node& node); }; struct EffectDAGNode { std::shared_ptr effect; std::vector input_nodes; std::vector output_nodes; int execution_order; }; class Sequence { public: Sequence(const GpuContext& ctx, int width, int height); virtual ~Sequence() = default; 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); void init_effect_nodes(); void set_sink_view(WGPUTextureView view) { nodes_.set_external_view("sink", view); } void set_source_view(WGPUTextureView view) { nodes_.set_external_view("source", view); } const std::vector& get_effect_dag() const { return effect_dag_; } protected: const GpuContext& ctx_; int width_; int height_; NodeRegistry nodes_; std::vector effect_dag_; UniformsSequenceParams params_; UniformBuffer uniforms_buffer_; }; #endif // SEQUENCE_H