summaryrefslogtreecommitdiff
path: root/src/gpu/sequence.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/sequence.h')
-rw-r--r--src/gpu/sequence.h131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/gpu/sequence.h b/src/gpu/sequence.h
new file mode 100644
index 0000000..a33dedb
--- /dev/null
+++ b/src/gpu/sequence.h
@@ -0,0 +1,131 @@
+// Sequence: Explicit node system with DAG effect routing
+// 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 <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+class Effect;
+
+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<WGPUTextureView> 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<WGPUTextureView>
+ get_output_views(const std::vector<std::string>& names);
+
+ // Resize all nodes
+ void resize(int width, int height);
+
+ // Check if node exists
+ bool has_node(const std::string& name) const;
+
+ // Register external view (for source/sink managed externally)
+ void set_external_view(const std::string& name, WGPUTextureView view);
+
+ private:
+ WGPUDevice device_;
+ int default_width_;
+ int default_height_;
+ std::map<std::string, Node> nodes_;
+ std::map<std::string, std::string> aliases_; // name -> backing node name
+
+ void create_texture(Node& node);
+};
+
+struct EffectDAGNode {
+ std::shared_ptr<Effect> effect;
+ std::vector<std::string> input_nodes;
+ std::vector<std::string> output_nodes;
+ int execution_order; // Topologically sorted
+};
+
+class Sequence {
+ public:
+ Sequence(const GpuContext& ctx, int width, int height);
+ virtual ~Sequence() = 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);
+
+ // Initialize effect nodes (call at end of subclass constructor)
+ void init_effect_nodes();
+
+ // Set surface texture view for rendering (sink node)
+ void set_sink_view(WGPUTextureView view) {
+ nodes_.set_external_view("sink", view);
+ }
+
+ // Set source texture view (input framebuffer)
+ void set_source_view(WGPUTextureView view) {
+ nodes_.set_external_view("source", view);
+ }
+
+ // Test accessor
+ const std::vector<EffectDAGNode>& get_effect_dag() const {
+ return effect_dag_;
+ }
+
+ protected:
+ const GpuContext& ctx_;
+ int width_;
+ int height_;
+ NodeRegistry nodes_;
+ std::vector<EffectDAGNode> effect_dag_;
+ UniformsSequenceParams params_;
+ UniformBuffer<UniformsSequenceParams> uniforms_buffer_;
+};
+#endif // SEQUENCE_H