summaryrefslogtreecommitdiff
path: root/src/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/demo_effects.h4
-rw-r--r--src/gpu/effect.cc14
-rw-r--r--src/gpu/effect.h21
-rw-r--r--src/gpu/sequence.cc8
4 files changed, 46 insertions, 1 deletions
diff --git a/src/gpu/demo_effects.h b/src/gpu/demo_effects.h
index 66b920c..77e5c76 100644
--- a/src/gpu/demo_effects.h
+++ b/src/gpu/demo_effects.h
@@ -32,9 +32,11 @@
#include "effects/scratch_effect.h"
#include "effects/ntsc_effect.h"
-// CNN v3 G-buffer + inference
+// CNN v3 G-buffer + inference + debug view
#include "../../cnn_v3/src/gbuffer_effect.h"
#include "../../cnn_v3/src/cnn_v3_effect.h"
+#include "../../cnn_v3/src/gbuf_view_effect.h"
+#include "../../cnn_v3/src/gbuf_deferred_effect.h"
// TODO: Port CNN effects
// #include "../../cnn_v1/src/cnn_v1_effect.h"
diff --git a/src/gpu/effect.cc b/src/gpu/effect.cc
index 4230021..1257090 100644
--- a/src/gpu/effect.cc
+++ b/src/gpu/effect.cc
@@ -58,6 +58,20 @@ void Effect::blit_input_to_output(WGPUCommandEncoder encoder,
&extent);
}
+std::string Effect::find_downstream_output(
+ const std::vector<EffectDAGNode>& dag) const {
+ for (const auto& node : dag) {
+ for (const auto& in : node.input_nodes) {
+ for (const auto& out : output_nodes_) {
+ if (in == out && !node.output_nodes.empty()) {
+ return node.output_nodes[0];
+ }
+ }
+ }
+ }
+ return "";
+}
+
void Effect::create_linear_sampler() {
sampler_.set(gpu_create_linear_sampler(ctx_.device));
}
diff --git a/src/gpu/effect.h b/src/gpu/effect.h
index 8055783..6c50d84 100644
--- a/src/gpu/effect.h
+++ b/src/gpu/effect.h
@@ -34,6 +34,20 @@ class Effect {
const UniformsSequenceParams& params,
NodeRegistry& nodes) = 0;
+ // Called after ALL effects in the sequence have rendered for this frame.
+ // Use for end-of-frame bookkeeping (e.g. copying temporal feedback buffers).
+ virtual void post_render(WGPUCommandEncoder encoder, NodeRegistry& nodes) {
+ (void)encoder;
+ (void)nodes;
+ }
+
+ // Called once after the full DAG is built (init_effect_nodes).
+ // Override to auto-wire inter-effect dependencies (e.g. temporal feedback).
+ // Default is a no-op.
+ virtual void wire_dag(const std::vector<struct EffectDAGNode>& dag) {
+ (void)dag;
+ }
+
virtual void resize(int width, int height) {
width_ = width;
height_ = height;
@@ -60,6 +74,13 @@ class Effect {
Texture dummy_texture_;
TextureView dummy_texture_view_;
+ // DAG query helpers (callable from wire_dag overrides)
+ //
+ // Returns output_nodes[0] of the first effect in |dag| whose input_nodes
+ // intersect this effect's output_nodes_ (i.e. the first direct downstream
+ // consumer). Returns "" if no such effect exists or it has no outputs.
+ std::string find_downstream_output(const std::vector<EffectDAGNode>& dag) const;
+
// Helper: Create linear sampler (call in subclass constructor if needed)
void create_linear_sampler();
diff --git a/src/gpu/sequence.cc b/src/gpu/sequence.cc
index 91ca187..6bff34e 100644
--- a/src/gpu/sequence.cc
+++ b/src/gpu/sequence.cc
@@ -269,6 +269,11 @@ void Sequence::render_effects(WGPUCommandEncoder encoder) {
for (const auto& dag_node : effect_dag_) {
dag_node.effect->dispatch_render(encoder, params_, nodes_);
}
+ // End-of-frame hook: allows effects to persist data for the next frame
+ // (e.g. temporal feedback copies) after all rendering is done.
+ for (const auto& dag_node : effect_dag_) {
+ dag_node.effect->post_render(encoder, nodes_);
+ }
}
void Sequence::resize(int width, int height) {
@@ -286,4 +291,7 @@ void Sequence::init_effect_nodes() {
for (auto& dag_node : effect_dag_) {
dag_node.effect->declare_nodes(nodes_);
}
+ for (auto& dag_node : effect_dag_) {
+ dag_node.effect->wire_dag(effect_dag_);
+ }
}