1use api::units::PictureRect;
6use crate::pattern::{PatternKind, PatternShaderInput};
7use crate::{spatial_tree::SpatialNodeIndex, render_task_graph::RenderTaskId, surface::SurfaceTileDescriptor, picture::TileKey, renderer::GpuBufferAddress, FastHashMap, prim_store::PrimitiveInstanceIndex, gpu_cache::GpuCacheAddress};
8use crate::gpu_types::{QuadSegment, TransformPaletteId};
9use crate::segment::EdgeAaSegmentMask;
10
11#[cfg_attr(feature = "capture", derive(Serialize))]
13#[cfg_attr(feature = "replay", derive(Deserialize))]
14#[derive(Debug, Copy, Clone)]
15pub struct Command(u32);
16
17impl Command {
18 const CMD_DRAW_SIMPLE_PRIM: u32 = 0x00000000;
20 const CMD_SET_SPATIAL_NODE: u32 = 0x10000000;
22 const CMD_DRAW_COMPLEX_PRIM: u32 = 0x20000000;
24 const CMD_DRAW_INSTANCE: u32 = 0x30000000;
26 const CMD_DRAW_QUAD: u32 = 0x40000000;
28 const CMD_SET_SEGMENTS: u32 = 0x50000000;
30
31 const CMD_MASK: u32 = 0xf0000000;
33 const PARAM_MASK: u32 = 0x0fffffff;
35
36 fn draw_simple_prim(prim_instance_index: PrimitiveInstanceIndex) -> Self {
38 Command(Command::CMD_DRAW_SIMPLE_PRIM | prim_instance_index.0)
39 }
40
41 fn set_spatial_node(spatial_node_index: SpatialNodeIndex) -> Self {
43 Command(Command::CMD_SET_SPATIAL_NODE | spatial_node_index.0)
44 }
45
46 fn set_segments(count: usize) -> Self {
48 Command(Command::CMD_SET_SEGMENTS | count as u32)
49 }
50
51 fn draw_complex_prim(prim_instance_index: PrimitiveInstanceIndex) -> Self {
53 Command(Command::CMD_DRAW_COMPLEX_PRIM | prim_instance_index.0)
54 }
55
56 fn draw_instance(prim_instance_index: PrimitiveInstanceIndex) -> Self {
57 Command(Command::CMD_DRAW_INSTANCE | prim_instance_index.0)
58 }
59
60 fn data(data: u32) -> Self {
62 Command(data)
63 }
64
65 fn draw_quad(prim_instance_index: PrimitiveInstanceIndex) -> Self {
66 Command(Command::CMD_DRAW_QUAD | prim_instance_index.0)
67 }
68}
69
70bitflags! {
71 #[repr(transparent)]
73 #[cfg_attr(feature = "capture", derive(Serialize))]
74 #[cfg_attr(feature = "replay", derive(Deserialize))]
75 #[derive(Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
76 pub struct QuadFlags : u8 {
77 const IS_OPAQUE = 1 << 0;
78
79 const APPLY_RENDER_TASK_CLIP = 1 << 1;
82
83 const IGNORE_DEVICE_PIXEL_SCALE = 1 << 2;
85
86 const USE_AA_SEGMENTS = 1 << 3;
88
89 const IS_MASK = 1 << 4;
93 }
94}
95
96bitflags! {
97 #[repr(transparent)]
99 #[cfg_attr(feature = "capture", derive(Serialize))]
100 #[cfg_attr(feature = "replay", derive(Deserialize))]
101 #[derive(Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
102 pub struct MaskFlags : i32 {
103 const PRIM_SPACE = 1 << 0;
104 }
105}
106
107#[cfg_attr(feature = "capture", derive(Serialize))]
109pub enum PrimitiveCommand {
110 Simple {
111 prim_instance_index: PrimitiveInstanceIndex,
112 },
113 Complex {
114 prim_instance_index: PrimitiveInstanceIndex,
115 gpu_address: GpuCacheAddress,
116 },
117 Instance {
118 prim_instance_index: PrimitiveInstanceIndex,
119 gpu_buffer_address: GpuBufferAddress,
120 },
121 Quad {
122 pattern: PatternKind,
123 pattern_input: PatternShaderInput,
124 src_color_task_id: RenderTaskId,
125 prim_instance_index: PrimitiveInstanceIndex,
127 gpu_buffer_address: GpuBufferAddress,
128 transform_id: TransformPaletteId,
129 quad_flags: QuadFlags,
130 edge_flags: EdgeAaSegmentMask,
131 },
132}
133
134impl PrimitiveCommand {
135 pub fn simple(
136 prim_instance_index: PrimitiveInstanceIndex,
137 ) -> Self {
138 PrimitiveCommand::Simple {
139 prim_instance_index,
140 }
141 }
142
143 pub fn complex(
144 prim_instance_index: PrimitiveInstanceIndex,
145 gpu_address: GpuCacheAddress,
146 ) -> Self {
147 PrimitiveCommand::Complex {
148 prim_instance_index,
149 gpu_address,
150 }
151 }
152
153 pub fn quad(
154 pattern: PatternKind,
155 pattern_input: PatternShaderInput,
156 src_color_task_id: RenderTaskId,
157 prim_instance_index: PrimitiveInstanceIndex,
158 gpu_buffer_address: GpuBufferAddress,
159 transform_id: TransformPaletteId,
160 quad_flags: QuadFlags,
161 edge_flags: EdgeAaSegmentMask,
162 ) -> Self {
163 PrimitiveCommand::Quad {
164 pattern,
165 pattern_input,
166 src_color_task_id,
167 prim_instance_index,
168 gpu_buffer_address,
169 transform_id,
170 quad_flags,
171 edge_flags,
172 }
173 }
174
175 pub fn instance(
176 prim_instance_index: PrimitiveInstanceIndex,
177 gpu_buffer_address: GpuBufferAddress,
178 ) -> Self {
179 PrimitiveCommand::Instance {
180 prim_instance_index,
181 gpu_buffer_address,
182 }
183 }
184}
185
186
187#[cfg_attr(feature = "capture", derive(Serialize))]
189#[cfg_attr(feature = "replay", derive(Deserialize))]
190pub struct CommandBuffer {
191 commands: Vec<Command>,
193 current_spatial_node_index: SpatialNodeIndex,
195}
196
197impl CommandBuffer {
198 pub fn new() -> Self {
200 CommandBuffer {
201 commands: Vec::new(),
202 current_spatial_node_index: SpatialNodeIndex::INVALID,
203 }
204 }
205
206 pub fn set_segments(
208 &mut self,
209 segments: &[QuadSegment],
210 ) {
211 self.commands.push(Command::set_segments(segments.len()));
212 for segment in segments {
213 self.commands.push(Command::data(segment.task_id.index));
214 }
215 }
216
217 pub fn add_prim(
219 &mut self,
220 prim_cmd: &PrimitiveCommand,
221 spatial_node_index: SpatialNodeIndex,
222 ) {
223 if self.current_spatial_node_index != spatial_node_index {
224 self.commands.push(Command::set_spatial_node(spatial_node_index));
225 self.current_spatial_node_index = spatial_node_index;
226 }
227
228 self.add_cmd(prim_cmd);
229 }
230
231 pub fn add_cmd(
233 &mut self,
234 prim_cmd: &PrimitiveCommand,
235 ) {
236 match *prim_cmd {
237 PrimitiveCommand::Simple { prim_instance_index } => {
238 self.commands.push(Command::draw_simple_prim(prim_instance_index));
239 }
240 PrimitiveCommand::Complex { prim_instance_index, gpu_address } => {
241 self.commands.push(Command::draw_complex_prim(prim_instance_index));
242 self.commands.push(Command::data((gpu_address.u as u32) << 16 | gpu_address.v as u32));
243 }
244 PrimitiveCommand::Instance { prim_instance_index, gpu_buffer_address } => {
245 self.commands.push(Command::draw_instance(prim_instance_index));
246 self.commands.push(Command::data((gpu_buffer_address.u as u32) << 16 | gpu_buffer_address.v as u32));
247 }
248 PrimitiveCommand::Quad { pattern, pattern_input, prim_instance_index, gpu_buffer_address, transform_id, quad_flags, edge_flags, src_color_task_id } => {
249 self.commands.push(Command::draw_quad(prim_instance_index));
250 self.commands.push(Command::data(pattern as u32));
251 self.commands.push(Command::data(pattern_input.0 as u32));
252 self.commands.push(Command::data(pattern_input.1 as u32));
253 self.commands.push(Command::data(src_color_task_id.index));
254 self.commands.push(Command::data((gpu_buffer_address.u as u32) << 16 | gpu_buffer_address.v as u32));
255 self.commands.push(Command::data(transform_id.0));
256 self.commands.push(Command::data((quad_flags.bits() as u32) << 16 | edge_flags.bits() as u32));
257 }
258 }
259 }
260
261 pub fn iter_prims<F>(
263 &self,
264 f: &mut F,
265 ) where F: FnMut(&PrimitiveCommand, SpatialNodeIndex, &[RenderTaskId]) {
266 let mut current_spatial_node_index = SpatialNodeIndex::INVALID;
267 let mut cmd_iter = self.commands.iter();
268 let mut segments = Vec::new();
270
271 while let Some(cmd) = cmd_iter.next() {
272 let command = cmd.0 & Command::CMD_MASK;
273 let param = cmd.0 & Command::PARAM_MASK;
274
275 match command {
276 Command::CMD_DRAW_SIMPLE_PRIM => {
277 let prim_instance_index = PrimitiveInstanceIndex(param);
278 let cmd = PrimitiveCommand::simple(prim_instance_index);
279 f(&cmd, current_spatial_node_index, &[]);
280 }
281 Command::CMD_SET_SPATIAL_NODE => {
282 current_spatial_node_index = SpatialNodeIndex(param);
283 }
284 Command::CMD_DRAW_COMPLEX_PRIM => {
285 let prim_instance_index = PrimitiveInstanceIndex(param);
286 let data = cmd_iter.next().unwrap();
287 let gpu_address = GpuCacheAddress {
288 u: (data.0 >> 16) as u16,
289 v: (data.0 & 0xffff) as u16,
290 };
291 let cmd = PrimitiveCommand::complex(
292 prim_instance_index,
293 gpu_address,
294 );
295 f(&cmd, current_spatial_node_index, &[]);
296 }
297 Command::CMD_DRAW_QUAD => {
298 let prim_instance_index = PrimitiveInstanceIndex(param);
299 let pattern = PatternKind::from_u32(cmd_iter.next().unwrap().0);
300 let pattern_input = PatternShaderInput(
301 cmd_iter.next().unwrap().0 as i32,
302 cmd_iter.next().unwrap().0 as i32,
303 );
304 let src_color_task_id = RenderTaskId { index: cmd_iter.next().unwrap().0 };
305 let data = cmd_iter.next().unwrap();
306 let transform_id = TransformPaletteId(cmd_iter.next().unwrap().0);
307 let bits = cmd_iter.next().unwrap().0;
308 let quad_flags = QuadFlags::from_bits((bits >> 16) as u8).unwrap();
309 let edge_flags = EdgeAaSegmentMask::from_bits((bits & 0xff) as u8).unwrap();
310 let gpu_buffer_address = GpuBufferAddress {
311 u: (data.0 >> 16) as u16,
312 v: (data.0 & 0xffff) as u16,
313 };
314 let cmd = PrimitiveCommand::quad(
315 pattern,
316 pattern_input,
317 src_color_task_id,
318 prim_instance_index,
319 gpu_buffer_address,
320 transform_id,
321 quad_flags,
322 edge_flags,
323 );
324 f(&cmd, current_spatial_node_index, &segments);
325 segments.clear()
326 }
327 Command::CMD_DRAW_INSTANCE => {
328 let prim_instance_index = PrimitiveInstanceIndex(param);
329 let data = cmd_iter.next().unwrap();
330 let gpu_buffer_address = GpuBufferAddress {
331 u: (data.0 >> 16) as u16,
332 v: (data.0 & 0xffff) as u16,
333 };
334 let cmd = PrimitiveCommand::instance(
335 prim_instance_index,
336 gpu_buffer_address,
337 );
338 f(&cmd, current_spatial_node_index, &[]);
339 }
340 Command::CMD_SET_SEGMENTS => {
341 let count = param;
342 for _ in 0 .. count {
343 segments.push(RenderTaskId { index: cmd_iter.next().unwrap().0 });
344 }
345 }
346 _ => {
347 unreachable!();
348 }
349 }
350 }
351 }
352}
353
354#[cfg_attr(feature = "capture", derive(Serialize))]
357#[cfg_attr(feature = "replay", derive(Deserialize))]
358pub enum CommandBufferBuilderKind {
359 Tiled {
360 tiles: FastHashMap<TileKey, SurfaceTileDescriptor>,
365 },
366 Simple {
367 render_task_id: RenderTaskId,
368 root_task_id: Option<RenderTaskId>,
369 dirty_rect: PictureRect,
370 },
371 Invalid,
372}
373
374#[cfg_attr(feature = "capture", derive(Serialize))]
375#[cfg_attr(feature = "replay", derive(Deserialize))]
376pub struct CommandBufferBuilder {
377 pub kind: CommandBufferBuilderKind,
378
379 pub establishes_sub_graph: bool,
384
385 pub resolve_source: Option<RenderTaskId>,
388
389 pub extra_dependencies: Vec<RenderTaskId>,
391}
392
393impl CommandBufferBuilder {
394 pub fn empty() -> Self {
395 CommandBufferBuilder {
396 kind: CommandBufferBuilderKind::Invalid,
397 establishes_sub_graph: false,
398 resolve_source: None,
399 extra_dependencies: Vec::new(),
400 }
401 }
402
403 pub fn new_tiled(
405 tiles: FastHashMap<TileKey, SurfaceTileDescriptor>,
406 ) -> Self {
407 CommandBufferBuilder {
408 kind: CommandBufferBuilderKind::Tiled {
409 tiles,
410 },
411 establishes_sub_graph: false,
412 resolve_source: None,
413 extra_dependencies: Vec::new(),
414 }
415 }
416
417 pub fn new_simple(
419 render_task_id: RenderTaskId,
420 establishes_sub_graph: bool,
421 root_task_id: Option<RenderTaskId>,
422 dirty_rect: PictureRect,
423 ) -> Self {
424 CommandBufferBuilder {
425 kind: CommandBufferBuilderKind::Simple {
426 render_task_id,
427 root_task_id,
428 dirty_rect,
429 },
430 establishes_sub_graph,
431 resolve_source: None,
432 extra_dependencies: Vec::new(),
433 }
434 }
435}
436
437#[cfg_attr(feature = "capture", derive(Serialize))]
439#[cfg_attr(feature = "replay", derive(Deserialize))]
440#[derive(Debug, Copy, Clone)]
441pub struct CommandBufferIndex(pub u32);
442
443pub struct CommandBufferList {
445 cmd_buffers: Vec<CommandBuffer>,
446}
447
448impl CommandBufferList {
449 pub fn new() -> Self {
450 CommandBufferList {
451 cmd_buffers: Vec::new(),
452 }
453 }
454
455 pub fn create_cmd_buffer(
456 &mut self,
457 ) -> CommandBufferIndex {
458 let index = CommandBufferIndex(self.cmd_buffers.len() as u32);
459 self.cmd_buffers.push(CommandBuffer::new());
460 index
461 }
462
463 pub fn get(&self, index: CommandBufferIndex) -> &CommandBuffer {
464 &self.cmd_buffers[index.0 as usize]
465 }
466
467 pub fn get_mut(&mut self, index: CommandBufferIndex) -> &mut CommandBuffer {
468 &mut self.cmd_buffers[index.0 as usize]
469 }
470}