//! 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)), &[...]);
//!     }
//! }
//! ```

mod error;
mod graph;
mod pass;
mod resources;

pub use error::{RenderGraphError, Result};
pub use graph::{PoolSlot, RenderGraph, ResourceAliasingInfo};
pub use pass::{
    BufferBuilder, ColorTextureBuilder, DepthTextureBuilder, GraphNode, PassBuilder,
    PassExecutionContext, PassNode, ResourcePool, ResourceTemplate, SlotValue, SubGraphInputSlot,
    SubGraphRunCommand,
};
pub use resources::{
    RenderGraphBufferDescriptor, RenderGraphResources, RenderGraphTextureDescriptor,
    ResourceDescriptor, ResourceHandle, ResourceId, ResourceType,
};
