summaryrefslogtreecommitdiff
path: root/doc/SEQUENCE.md
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-03-23 07:54:18 +0100
committerskal <pascal.massimino@gmail.com>2026-03-23 07:54:18 +0100
commit491a3c1ccbd0f46be655e97d2e3697135df6e3a2 (patch)
tree57e9d7d8732fe7a0625d99641e780b38ace4c765 /doc/SEQUENCE.md
parent1e3813355e37f903314ec2069ff788c6f69becfd (diff)
feat(gbuffer): wire_dag() + find_downstream_output() for temporal feedback
- Add Effect::wire_dag() virtual (called from init_effect_nodes after full DAG built) - Add Effect::find_downstream_output() protected helper (first downstream consumer output) - GBufferEffect::wire_dag() auto-sets cnn_output_node_ via find_downstream_output, guarding against sink (external view, null texture) - GBufferEffect::post_render() null-checks src texture before CopyTextureToTexture - Tests: find_downstream_output cases + wire_dag integration in test_effect_base - Doc: SEQUENCE.md updated with wire_dag pattern, helper contract, and sink guard Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'doc/SEQUENCE.md')
-rw-r--r--doc/SEQUENCE.md49
1 files changed, 48 insertions, 1 deletions
diff --git a/doc/SEQUENCE.md b/doc/SEQUENCE.md
index 411e9d4..ca45756 100644
--- a/doc/SEQUENCE.md
+++ b/doc/SEQUENCE.md
@@ -158,7 +158,54 @@ sequence and no post-CNN effects overwrite `sink`. `post_render()` is
unconditionally correct regardless of sequence structure.
**Current user**: `GBufferEffect` uses this pattern for `prev.rgb` (CNN temporal
-feedback). Call `gbuf->set_cnn_output_node("cnn_out_node")` once at setup.
+feedback). `cnn_output_node_` is wired automatically via `wire_dag()` — no
+manual `set_cnn_output_node()` call needed.
+
+### DAG wiring (`wire_dag`)
+
+```cpp
+// Effect base class
+virtual void wire_dag(const std::vector<EffectDAGNode>& dag) {}
+```
+
+Called once from `Sequence::init_effect_nodes()` after all `declare_nodes()`
+calls, so the full DAG is visible. Override to resolve inter-effect
+dependencies that cannot be expressed through node names alone.
+
+`GBufferEffect::wire_dag()` delegates to the base-class helper
+`find_downstream_output(dag)`, then guards against wiring to `"sink"`:
+
+```cpp
+void GBufferEffect::wire_dag(const std::vector<EffectDAGNode>& dag) {
+ const std::string out = find_downstream_output(dag);
+ if (out != "sink") cnn_output_node_ = out;
+}
+```
+
+`"sink"` is registered as an external view (`texture == nullptr`); copying
+from it in `post_render` would crash. When no CNN follows the G-buffer stage
+(e.g. debug/deferred sequences), `cnn_output_node_` stays empty and
+`post_render` is a no-op.
+
+#### `Effect::find_downstream_output`
+
+```cpp
+// protected helper — call from wire_dag()
+std::string find_downstream_output(const std::vector<EffectDAGNode>& dag) const;
+```
+
+Returns `output_nodes[0]` of the first direct downstream consumer in the DAG,
+or `""` if none exists. The helper is agnostic about node semantics — it is
+the **caller's responsibility** to reject unsuitable results (e.g. `"sink"` or
+any other external/terminal node whose texture is not owned by the registry).
+
+`post_render` also null-checks the source texture as a belt-and-suspenders
+guard:
+
+```cpp
+WGPUTexture src_tex = nodes.get_texture(cnn_output_node_);
+if (!src_tex) return; // external view — no owned texture to copy
+```
### Node System