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