tessera_ui/renderer/command.rs
1//! Unified command system for rendering and computation.
2//!
3//! This module defines the `Command` enum that unifies draw and compute operations
4//! into a single type, enabling seamless integration of graphics and compute pipelines
5//! in the rendering workflow.
6
7use std::any::Any;
8
9use crate::{
10 ComputeCommand, DrawCommand,
11 px::{Px, PxRect},
12};
13
14/// Defines the sampling requirements for a rendering command that needs a barrier.
15#[derive(Debug, Clone, Copy, PartialEq)]
16pub enum BarrierRequirement {
17 /// The command needs to sample from the entire previously rendered scene.
18 /// This will cause a full-screen texture copy.
19 Global,
20
21 /// The command needs to sample from a region relative to its own bounding box.
22 /// The `padding` value extends the sampling area beyond the component's own size.
23 /// For example, a `padding` of `10.0` on all sides means the component can
24 /// access pixels up to 10px outside its own boundaries.
25 PaddedLocal {
26 top: Px,
27 right: Px,
28 bottom: Px,
29 left: Px,
30 },
31
32 /// The command needs to sample from a specific, absolute region of the screen.
33 Absolute(PxRect),
34}
35
36impl BarrierRequirement {
37 pub const ZERO_PADDING_LOCAL: Self = Self::PaddedLocal {
38 top: Px::ZERO,
39 right: Px::ZERO,
40 bottom: Px::ZERO,
41 left: Px::ZERO,
42 };
43
44 /// Creates a `PaddedLocal` barrier requirement with uniform padding on all sides.
45 #[must_use]
46 pub const fn uniform_padding_local(padding: Px) -> Self {
47 Self::PaddedLocal {
48 top: padding,
49 right: padding,
50 bottom: padding,
51 left: padding,
52 }
53 }
54}
55
56/// Trait providing type erasure capabilities for command objects.
57///
58/// This trait allows commands to be stored and passed around as trait objects
59/// while still providing access to their concrete types when needed for
60/// pipeline dispatch.
61pub trait AsAny {
62 /// Returns a reference to the concrete type as `&dyn Any`.
63 fn as_any(&self) -> &dyn Any;
64}
65
66/// Blanket implementation of `AsAny` for all types that implement `Any`.
67impl<T: Any> AsAny for T {
68 fn as_any(&self) -> &dyn Any {
69 self
70 }
71}
72
73/// Unified command enum that can represent either a draw or compute operation.
74///
75/// This enum enables the rendering system to process both graphics and compute
76/// commands in a unified pipeline, with proper barrier handling for multi-pass
77/// rendering scenarios.
78pub enum Command {
79 /// A graphics rendering command processed by draw pipelines
80 Draw(Box<dyn DrawCommand>),
81 /// A GPU computation command processed by compute pipelines
82 Compute(Box<dyn ComputeCommand>),
83 /// A command to push a clipping rectangle onto the stack
84 ClipPush(PxRect),
85 /// A command to pop the most recent clipping rectangle from the stack
86 ClipPop,
87}
88
89impl Command {
90 /// Returns the barrier requirement for this command.
91 ///
92 /// Commands that need to sample from previously rendered content
93 /// should return a barrier requirement to ensure proper synchronization.
94 #[must_use]
95 pub fn barrier(&self) -> Option<BarrierRequirement> {
96 match self {
97 Self::Draw(command) => command.barrier(),
98 // Currently, compute can only be used for after effects,
99 Self::Compute(command) => Some(command.barrier()),
100 Self::ClipPush(_) | Self::ClipPop => None, // Clipping commands do not require barriers
101 }
102 }
103}
104
105impl Clone for Command {
106 fn clone(&self) -> Self {
107 match self {
108 Self::Draw(cmd) => Self::Draw(cmd.clone_box()),
109 Self::Compute(cmd) => Self::Compute(cmd.clone_box()),
110 Self::ClipPush(rect) => Self::ClipPush(*rect),
111 Self::ClipPop => Self::ClipPop,
112 }
113 }
114}
115
116/// Automatic conversion from boxed draw commands to unified commands
117impl From<Box<dyn DrawCommand>> for Command {
118 fn from(val: Box<dyn DrawCommand>) -> Self {
119 Self::Draw(val)
120 }
121}
122
123/// Automatic conversion from boxed compute commands to unified commands
124impl From<Box<dyn ComputeCommand>> for Command {
125 fn from(val: Box<dyn ComputeCommand>) -> Self {
126 Self::Compute(val)
127 }
128}