1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
//! Frame graph rendering system for composable render pipelines.
//!
//! Build complex rendering pipelines by declaring passes and their resource dependencies:
//!
//! - [`RenderGraph`]: Main graph structure that schedules and executes render passes
//! - [`PassNode`]: Trait for implementing custom render passes
//! - [`PassExecutionContext`]: Runtime context for accessing resources during execution
//! - [`ResourceId`]: Handle to a graph-managed texture or buffer
//!
//! The render graph automatically handles:
//! - Pass ordering based on resource dependencies
//! - Transient resource allocation and aliasing
//! - Load/store operation optimization
//! - Dead pass culling
//!
//! # Basic Graph Setup
//!
//! ```ignore
//! use nightshade::render::wgpu::rendergraph::{RenderGraph, PassNode, PassExecutionContext};
//!
//! let mut graph = RenderGraph::new();
//!
//! // Declare resources
//! let depth = graph.add_depth_texture("depth")
//! .size(1920, 1080)
//! .clear_depth(0.0)
//! .transient();
//!
//! let scene_color = graph.add_color_texture("scene_color")
//! .format(wgpu::TextureFormat::Rgba16Float)
//! .size(1920, 1080)
//! .clear_color(wgpu::Color::BLACK)
//! .transient();
//!
//! let swapchain = graph.add_color_texture("swapchain")
//! .format(wgpu::TextureFormat::Bgra8UnormSrgb)
//! .external(); // Provided each frame
//!
//! // Add passes with their resource bindings
//! graph.add_pass(Box::new(scene_pass), &[
//! ("color", scene_color),
//! ("depth", depth),
//! ])?;
//!
//! graph.add_pass(Box::new(post_process_pass), &[
//! ("input", scene_color),
//! ("output", swapchain),
//! ])?;
//!
//! graph.compile()?;
//! ```
//!
//! # Implementing a Custom Pass
//!
//! ```ignore
//! struct MyPass {
//! pipeline: wgpu::RenderPipeline,
//! }
//!
//! impl PassNode for MyPass {
//! fn name(&self) -> &str { "my_pass" }
//!
//! fn reads(&self) -> Vec<&str> { vec!["input"] }
//! fn writes(&self) -> Vec<&str> { vec!["output"] }
//!
//! fn execute<'r, 'e>(
//! &mut self,
//! ctx: PassExecutionContext<'r, 'e>,
//! ) -> Result<Vec<SubGraphRunCommand<'r>>> {
//! let (output_view, load_op, store_op) = ctx.get_color_attachment("output")?;
//! let input_view = ctx.get_texture_view("input")?;
//!
//! let mut pass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
//! color_attachments: &[Some(wgpu::RenderPassColorAttachment {
//! view: output_view,
//! resolve_target: None,
//! ops: wgpu::Operations { load: load_op, store: store_op },
//! })],
//! ..Default::default()
//! });
//!
//! pass.set_pipeline(&self.pipeline);
//! // Bind input_view to a bind group...
//! pass.draw(0..3, 0..1);
//!
//! Ok(vec![])
//! }
//! }
//! ```
//!
//! # Executing the Graph
//!
//! ```ignore
//! // Each frame:
//! graph.set_external_texture(swapchain_id, surface_view, width, height);
//!
//! let command_buffers = graph.execute(&device, &queue, &world)?;
//! queue.submit(command_buffers);
//! ```
//!
//! # Resource Types
//!
//! | Type | Description |
//! |------|-------------|
//! | Transient | Graph allocates/manages lifetime, can be aliased |
//! | External | Provided each frame (swapchain, imported textures) |
//!
//! # Pass Methods
//!
//! | Method | Description |
//! |--------|-------------|
//! | `name()` | Unique identifier for the pass |
//! | `reads()` | Slots this pass reads from |
//! | `writes()` | Slots this pass writes to |
//! | `reads_writes()` | Slots used for both read and write |
//! | `prepare()` | Called before execute, for uploading uniforms |
//! | `execute()` | Record GPU commands |
//!
//! # Context Methods
//!
//! | Method | Description |
//! |--------|-------------|
//! | `get_texture_view(slot)` | Get texture view for reading |
//! | `get_color_attachment(slot)` | Get view + load/store ops for color output |
//! | `get_depth_attachment(slot)` | Get view + load/store ops for depth output |
//! | `get_buffer(slot)` | Get buffer for compute passes |
//! | `get_texture_size(slot)` | Get dimensions of a texture |
//!
//! # Customizing the Engine's Render Graph
//!
//! Override [`State::configure_render_graph`](crate::run::State::configure_render_graph)
//! to modify or extend the default pipeline:
//!
//! ```ignore
//! impl State for MyGame {
//! fn configure_render_graph(
//! &mut self,
//! graph: &mut RenderGraph<World>,
//! device: &wgpu::Device,
//! ) {
//! // Disable a built-in pass
//! graph.set_pass_enabled("bloom_pass", false);
//!
//! // Or add your own post-process pass
//! // graph.add_pass(Box::new(MyEffect::new(device)), &[...]);
//! }
//! }
//! ```
pub use ;
pub use ;
pub use ;
pub use ;