/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/// A tightly packed command stored in a command buffer #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] #[derive(Debug, Copy, Clone)] pubstruct Command(u32);
impl Command { /// Draw a simple primitive that needs prim instance index only. const CMD_DRAW_SIMPLE_PRIM: u32 = 0x00000000; /// Change the current spatial node. const CMD_SET_SPATIAL_NODE: u32 = 0x10000000; /// Draw a complex (3d-split) primitive, that has multiple GPU cache addresses. const CMD_DRAW_COMPLEX_PRIM: u32 = 0x20000000; /// Draw a primitive, that has a single GPU buffer addresses. const CMD_DRAW_INSTANCE: u32 = 0x30000000; /// Draw a generic quad primitive const CMD_DRAW_QUAD: u32 = 0x40000000; /// Set a list of variable-length segments const CMD_SET_SEGMENTS: u32 = 0x50000000;
/// Bitmask for command bits of the command. const CMD_MASK: u32 = 0xf0000000; /// Bitmask for param bits of the command. const PARAM_MASK: u32 = 0x0fffffff;
/// If true, the prim is 2d and axis-aligned in device space. The render task rect can /// cheaply be used as a device-space clip in the vertex shader. const APPLY_RENDER_TASK_CLIP = 1 << 1;
/// If true, use segments for drawing the AA edges, to allow inner section to be opaque const USE_AA_SEGMENTS = 1 << 3;
/// If true, render as a mask. This ignores the blue, green and alpha channels and replaces /// them with the red channel in the fragment shader. Used with multiply blending, on top /// of premultiplied alpha content, it has the effect of applying a mask to the content under ir. const IS_MASK = 1 << 4;
}
}
bitflags! { /// Defines the space that a quad primitive is drawn in #[repr(transparent)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] #[derive(Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] pubstruct MaskFlags : i32 { const PRIM_SPACE = 1 << 0;
}
}
/// The unpacked equivalent to a `Command`. /// /// Each variant carries an `Index<PrimitiveDrawHeader>` identifying which /// per-frame draw header to use. While `scratch.frame.draws` is identity- /// indexed by `PrimitiveInstanceIndex.0`, the numerical value of the draw /// index equals the prim instance index; a follow-up will make them /// physically distinct when draws becomes push-per-draw. #[cfg_attr(feature = "capture", derive(Serialize))] pubenum PrimitiveCommand {
Simple {
draw_index: storage::Index<PrimitiveDrawHeader>,
},
Complex {
draw_index: storage::Index<PrimitiveDrawHeader>,
gpu_address: GpuBufferAddress,
},
Instance {
draw_index: storage::Index<PrimitiveDrawHeader>,
gpu_buffer_address: GpuBufferAddress,
},
Quad {
pattern: PatternKind,
pattern_input: PatternShaderInput,
src_color_task_id: RenderTaskId, // TODO(gw): Used for bounding rect only, could possibly remove
draw_index: storage::Index<PrimitiveDrawHeader>,
gpu_buffer_address: GpuBufferAddress,
transform_id: GpuTransformId,
quad_flags: QuadFlags,
edge_flags: EdgeMask,
blend_mode: BlendMode,
},
}
// Non-Advanced variants map to 0..=8; Advanced(mode) maps to 9 + mode as u32. // MixBlendMode is repr(u8) with values 0..=16, so Advanced covers 9..=25.
/// A list of commands describing how to draw a primitive list. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pubstruct CommandBuffer { /// The encoded drawing commands.
commands: Vec<Command>, /// Cached current spatial node.
current_spatial_node_index: SpatialNodeIndex,
}
/// Push a list of segments in to the cmd buffer pubfn set_segments(
&mutself,
segments: &[QuadSegment],
) { self.commands.push(Command::set_segments(segments.len())); for segment in segments { self.commands.push(Command::data(segment.task_id.index)); self.commands.push(Command::data(segment.task_id.sub_rect_index as u32));
}
}
/// Add a primitive to the command buffer. pubfn add_prim(
&mutself,
prim_cmd: &PrimitiveCommand,
spatial_node_index: SpatialNodeIndex,
) { ifself.current_spatial_node_index != spatial_node_index { self.commands.push(Command::set_spatial_node(spatial_node_index)); self.current_spatial_node_index = spatial_node_index;
}
/// Iterate the command list, calling a provided closure for each primitive draw command. pubfn iter_prims<F>(
&self,
f: &mut F,
) where F: FnMut(&PrimitiveCommand, SpatialNodeIndex, &[RenderTaskId]) { letmut current_spatial_node_index = SpatialNodeIndex::INVALID; letmut cmd_iter = self.commands.iter(); // TODO(gw): Consider pre-allocating this / Smallvec if it shows up in profiles. letmut segments = Vec::new();
whilelet Some(cmd) = cmd_iter.next() { let command = cmd.0 & Command::CMD_MASK; let param = cmd.0 & Command::PARAM_MASK;
match command {
Command::CMD_DRAW_SIMPLE_PRIM => { let draw_index = storage::Index::from_u32(param); let cmd = PrimitiveCommand::simple(draw_index);
f(&cmd, current_spatial_node_index, &[]);
}
Command::CMD_SET_SPATIAL_NODE => {
current_spatial_node_index = SpatialNodeIndex(param);
}
Command::CMD_DRAW_COMPLEX_PRIM => { let draw_index = storage::Index::from_u32(param); let data = cmd_iter.next().unwrap(); let gpu_address = GpuBufferAddress::from_u32(data.0); let cmd = PrimitiveCommand::complex(
draw_index,
gpu_address,
);
f(&cmd, current_spatial_node_index, &[]);
}
Command::CMD_DRAW_QUAD => { let draw_index = storage::Index::from_u32(param); let pattern = PatternKind::from_u32(cmd_iter.next().unwrap().0); let pattern_input = PatternShaderInput(
cmd_iter.next().unwrap().0as i32,
cmd_iter.next().unwrap().0as i32,
); let src_color_task_id = RenderTaskId {
index: cmd_iter.next().unwrap().0,
sub_rect_index: cmd_iter.next().unwrap().0as u16
}; let data = cmd_iter.next().unwrap(); let transform_id = GpuTransformId(cmd_iter.next().unwrap().0); let bits = cmd_iter.next().unwrap().0; let quad_flags = QuadFlags::from_bits((bits >> 16) as u8).unwrap(); let edge_flags = EdgeMask::from_bits((bits & 0xff) as u8).unwrap(); let blend_mode = decode_blend_mode(cmd_iter.next().unwrap().0); let gpu_buffer_address = GpuBufferAddress::from_u32(data.0); let cmd = PrimitiveCommand::quad(
pattern,
pattern_input,
src_color_task_id,
draw_index,
gpu_buffer_address,
transform_id,
quad_flags,
edge_flags,
blend_mode,
);
f(&cmd, current_spatial_node_index, &segments);
segments.clear()
}
Command::CMD_DRAW_INSTANCE => { let draw_index = storage::Index::from_u32(param); let data = cmd_iter.next().unwrap(); let gpu_buffer_address = GpuBufferAddress::from_u32(data.0); let cmd = PrimitiveCommand::instance(
draw_index,
gpu_buffer_address,
);
f(&cmd, current_spatial_node_index, &[]);
}
Command::CMD_SET_SEGMENTS => { let count = param; for _ in0 .. count {
segments.push(
RenderTaskId {
index: cmd_iter.next().unwrap().0,
sub_rect_index: cmd_iter.next().unwrap().0as u16,
}
);
}
}
_ => {
unreachable!();
}
}
}
}
}
/// Abstracts whether a command buffer is being built for a tiled (picture cache) /// or simple (child surface). #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pubenum CommandBufferBuilderKind {
Tiled { // TODO(gw): It might be worth storing this as a 2d-array instead // of a hash map if it ever shows up in profiles. This is // slightly complicated by the sub_slice_index in the // TileKey structure - could have a 2 level array?
tiles: FastHashMap<TileKey, SurfaceTileDescriptor>,
},
Simple {
render_task_id: RenderTaskId,
root_task_id: Option<RenderTaskId>,
dirty_rect: PictureRect,
},
Invalid,
}
/// If a command buffer establishes a sub-graph, then at the end of constructing /// the surface, the parent surface is supplied as an input dependency, and the /// parent surface gets a duplicated (existing) task with the same location, and /// with the sub-graph output as an input dependency. pub establishes_sub_graph: bool,
/// If this surface builds a sub-graph, it will mark a task in the filter sub-graph /// as a resolve source for the input from the parent surface. pub resolve_source: Option<RenderTaskId>,
/// List of render tasks that depend on the task that will be created for this builder. pub extra_dependencies: Vec<RenderTaskId>,
}
// Index into a command buffer stored in a `CommandBufferList`. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] #[derive(Debug, Copy, Clone)] pubstruct CommandBufferIndex(pub u32);
// Container for a list of command buffers that are built for a frame. pubstruct CommandBufferList {
cmd_buffers: Vec<CommandBuffer>,
}
pubfn create_cmd_buffer(
&mutself,
) -> CommandBufferIndex { let index = CommandBufferIndex(self.cmd_buffers.len() as u32); self.cmd_buffers.push(CommandBuffer::new());
index
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.