tessera_ui/render_scene.rs
1//! Render command definitions for frame graphs
2
3use downcast_rs::{Downcast, impl_downcast};
4use dyn_clone::DynClone;
5
6use crate::{
7 ComputeCommand, DrawCommand,
8 px::{Px, PxRect},
9};
10
11/// Defines the sampling requirements for a rendering command that needs a
12/// barrier.
13#[derive(Debug, Clone, Copy, PartialEq)]
14pub enum SampleRegion {
15 /// The command needs to sample from the entire previously rendered scene.
16 /// This will cause a full-screen texture copy.
17 Global,
18 /// The command needs to sample from a region relative to its own bounding
19 /// box.
20 PaddedLocal(PaddingRect),
21 /// The command needs to sample from a specific, absolute region of the
22 /// screen.
23 Absolute(PxRect),
24}
25
26/// Defines the drawing region for a rendering command.
27#[derive(Debug, Clone, Copy, PartialEq)]
28pub enum DrawRegion {
29 /// The command draws to the entire surface.
30 Global,
31 /// The command draws to a region relative to its own bounding box.
32 PaddedLocal(PaddingRect),
33 /// The command draws to a specific, absolute region of the screen.
34 Absolute(PxRect),
35}
36
37/// Padding values for all four sides of a rectangle.
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub struct PaddingRect {
40 /// Padding applied to the top edge.
41 pub top: Px,
42 /// Padding applied to the right edge.
43 pub right: Px,
44 /// Padding applied to the bottom edge.
45 pub bottom: Px,
46 /// Padding applied to the left edge.
47 pub left: Px,
48}
49
50impl PaddingRect {
51 /// A zero padding rectangle that leaves the sampling region unchanged.
52 pub const ZERO: Self = Self {
53 top: Px::ZERO,
54 right: Px::ZERO,
55 bottom: Px::ZERO,
56 left: Px::ZERO,
57 };
58
59 /// Creates a uniform padding rectangle with the same padding on all sides.
60 #[must_use]
61 pub const fn uniform(padding: Px) -> Self {
62 Self {
63 top: padding,
64 right: padding,
65 bottom: padding,
66 left: padding,
67 }
68 }
69}
70
71impl SampleRegion {
72 /// A zero-padding local barrier requirement for commands that only sample
73 /// within their bounds.
74 pub const ZERO_PADDING_LOCAL: Self = Self::PaddedLocal(PaddingRect::ZERO);
75
76 /// Creates a `PaddedLocal` barrier requirement with uniform sampling
77 /// padding on all sides.
78 #[must_use]
79 pub const fn uniform_padding_local(padding: Px) -> Self {
80 Self::PaddedLocal(PaddingRect::uniform(padding))
81 }
82}
83
84/// Trait for composite rendering commands that expand into draw/compute ops.
85pub trait CompositeCommand: DynClone + Downcast + Send + Sync {}
86
87impl_downcast!(CompositeCommand);
88
89dyn_clone::clone_trait_object!(CompositeCommand);
90
91/// Unified command enum that can represent either a draw or compute operation.
92///
93/// This enum enables the rendering system to process both graphics and compute
94/// commands in a unified pipeline, with proper barrier handling for multi-pass
95/// rendering scenarios.
96pub enum Command {
97 /// A graphics rendering command processed by draw pipelines.
98 Draw(Box<dyn DrawCommand>),
99 /// A GPU computation command processed by compute pipelines.
100 Compute(Box<dyn ComputeCommand>),
101 /// A composite command that expands into draw/compute operations.
102 Composite(Box<dyn CompositeCommand>),
103 /// A command to push a clipping rectangle onto the stack.
104 ClipPush(PxRect),
105 /// A command to pop the most recent clipping rectangle from the stack.
106 ClipPop,
107}
108
109impl Command {
110 /// Returns the barrier requirement for this command.
111 ///
112 /// Commands that need to sample from previously rendered content
113 /// should return a barrier requirement to ensure proper synchronization.
114 #[must_use]
115 pub fn barrier(&self) -> Option<SampleRegion> {
116 match self {
117 Self::Draw(command) => command.sample_region(),
118 // Currently, compute can only be used for after effects,
119 Self::Compute(command) => Some(command.barrier()),
120 Self::Composite(_) => None,
121 Self::ClipPush(_) | Self::ClipPop => None, // Clipping commands do not require barriers
122 }
123 }
124}
125
126impl Clone for Command {
127 fn clone(&self) -> Self {
128 match self {
129 Self::Draw(cmd) => Self::Draw(cmd.clone()),
130 Self::Compute(cmd) => Self::Compute(cmd.clone()),
131 Self::Composite(cmd) => Self::Composite(cmd.clone()),
132 Self::ClipPush(rect) => Self::ClipPush(*rect),
133 Self::ClipPop => Self::ClipPop,
134 }
135 }
136}
137
138/// Automatic conversion from boxed draw commands to unified commands.
139impl From<Box<dyn DrawCommand>> for Command {
140 fn from(val: Box<dyn DrawCommand>) -> Self {
141 Self::Draw(val)
142 }
143}
144
145/// Automatic conversion from boxed compute commands to unified commands.
146impl From<Box<dyn ComputeCommand>> for Command {
147 fn from(val: Box<dyn ComputeCommand>) -> Self {
148 Self::Compute(val)
149 }
150}
151
152/// Automatic conversion from boxed composite commands to unified commands.
153impl From<Box<dyn CompositeCommand>> for Command {
154 fn from(val: Box<dyn CompositeCommand>) -> Self {
155 Self::Composite(val)
156 }
157}