From 58a76f0f1604bb3eddb8d171daaa6bca08bb629c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 23 Jun 2020 13:02:15 -0700 Subject: [PATCH] Update `gpu_data` --- renderer/src/gpu_data.rs | 395 ++++++++++++++++++++++++++++++++------- 1 file changed, 324 insertions(+), 71 deletions(-) diff --git a/renderer/src/gpu_data.rs b/renderer/src/gpu_data.rs index 2282df5e..9c14fd3f 100644 --- a/renderer/src/gpu_data.rs +++ b/renderer/src/gpu_data.rs @@ -13,13 +13,15 @@ use crate::builder::{ALPHA_TILES_PER_LEVEL, ALPHA_TILE_LEVEL_COUNT}; use crate::options::BoundingQuad; use crate::paint::PaintCompositeOp; +use crate::scene::PathId; +use crate::tile_map::DenseTileMap; use pathfinder_color::ColorU; use pathfinder_content::effects::{BlendMode, Filter}; use pathfinder_content::render_target::RenderTargetId; -use pathfinder_geometry::line_segment::{LineSegmentU4, LineSegmentU8}; +use pathfinder_geometry::line_segment::{LineSegment2F, LineSegmentU16}; use pathfinder_geometry::rect::RectI; use pathfinder_geometry::transform2d::Transform2F; -use pathfinder_geometry::vector::Vector2I; +use pathfinder_geometry::vector::{Vector2F, Vector2I}; use pathfinder_gpu::TextureSamplingFlags; use std::fmt::{Debug, Formatter, Result as DebugResult}; use std::sync::Arc; @@ -64,13 +66,18 @@ pub enum RenderCommand { UploadTextureMetadata(Vec), // Adds fills to the queue. - AddFills(Vec), + AddFillsD3D9(Vec), // Flushes the queue of fills. - FlushFills, + FlushFillsD3D9, - // Renders clips to the mask tile. - ClipTiles(Vec), + /// Upload a scene to GPU. + /// + /// This will only be sent if dicing and binning is done on GPU. + UploadSceneD3D11 { + draw_segments: SegmentsD3D11, + clip_segments: SegmentsD3D11, + }, // Pushes a render target onto the stack. Draw commands go to the render target on top of the // stack. @@ -79,11 +86,14 @@ pub enum RenderCommand { // Pops a render target from the stack. PopRenderTarget, - // Marks that tile compositing is about to begin. - BeginTileDrawing, + // Computes backdrops for tiles, prepares any Z-buffers, and performs clipping. + PrepareClipTilesD3D11(TileBatchDataD3D11), // Draws a batch of tiles to the render target on top of the stack. - DrawTiles(TileBatch), + DrawTilesD3D9(DrawTileBatchD3D9), + + // Draws a batch of tiles to the render target on top of the stack. + DrawTilesD3D11(DrawTileBatchD3D11), // Presents a rendered frame. Finish { cpu_build_time: Duration }, @@ -103,13 +113,125 @@ pub struct TextureLocation { pub rect: RectI, } +/// Information about a batch of tiles to be prepared (postprocessed). #[derive(Clone, Debug)] -pub struct TileBatch { - pub tiles: Vec, +pub struct TileBatchDataD3D11 { + /// The ID of this batch. + /// + /// The renderer should not assume that these values are consecutive. + pub batch_id: TileBatchId, + /// The number of paths in this batch. + pub path_count: u32, + /// The number of tiles in this batch. + pub tile_count: u32, + /// The total number of segments in this batch. + pub segment_count: u32, + /// Information needed to prepare the tiles. + pub prepare_info: PrepareTilesInfoD3D11, + /// Where the paths come from (draw or clip). + pub path_source: PathSource, + /// Information about clips applied to paths, if any of the paths have clips. + pub clipped_path_info: Option, +} + +/// Where a path should come from (draw or clip). +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum PathSource { + Draw, + Clip, +} + +/// Information about a batch of tiles to be prepared on GPU. +#[derive(Clone, Debug)] +pub struct PrepareTilesInfoD3D11 { + /// Initial backdrop values for each tile column, packed together. + pub backdrops: Vec, + + /// Mapping from path index to metadata needed to compute propagation on GPU. + /// + /// This contains indices into the `tiles` vector. + pub propagate_metadata: Vec, + + /// Metadata about each path that will be diced (flattened). + pub dice_metadata: Vec, + + /// Sparse information about all the allocated tiles. + pub tile_path_info: Vec, + + /// A transform to apply to the segments. + pub transform: Transform2F, +} + +#[derive(Clone, Debug)] +pub struct SegmentsD3D11 { + pub points: Vec, + pub indices: Vec, +} + +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub struct SegmentIndicesD3D11 { + pub first_point_index: u32, + pub flags: u32, +} + +/// Information about clips applied to paths in a batch. +#[derive(Clone, Debug)] +pub struct ClippedPathInfo { + /// The ID of the batch containing the clips. + /// + /// In the current implementation, this is always 0. + pub clip_batch_id: TileBatchId, + + /// The number of paths that have clips. + pub clipped_path_count: u32, + + /// The maximum number of clipped tiles. + /// + /// This is used to allocate vertex buffers. + pub max_clipped_tile_count: u32, + + /// The actual clips, if calculated on CPU. + pub clips: Option>, +} + +/// Together with the `TileBatchId`, uniquely identifies a path on the renderer side. +/// +/// Generally, `PathIndex(!0)` represents no path. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub struct PathBatchIndex(pub u32); + +/// Unique ID that identifies a batch of tiles. +#[derive(Clone, Copy, PartialEq, Debug)] +pub struct TileBatchId(pub u32); + +#[derive(Clone, Debug)] +pub enum DrawTileBatch { + D3D9(DrawTileBatchD3D9), + D3D11(DrawTileBatchD3D11), +} + +/// Information needed to draw a batch of tiles in D3D9. +#[derive(Clone, Debug)] +pub struct DrawTileBatchD3D9 { + pub tiles: Vec, + pub clips: Vec, + pub z_buffer_data: DenseTileMap, + /// The color texture to use. pub color_texture: Option, + /// The filter to use. pub filter: Filter, + /// The blend mode to composite these tiles with. pub blend_mode: BlendMode, - pub tile_page: u16, +} + +/// Information needed to draw a batch of tiles in D3D11. +#[derive(Clone, Debug)] +pub struct DrawTileBatchD3D11 { + /// Data for the tile batch. + pub tile_batch_data: TileBatchDataD3D11, + /// The color texture to use. + pub color_texture: Option, } #[derive(Clone, Copy, Debug, PartialEq)] @@ -119,90 +241,198 @@ pub struct TileBatchTexture { pub composite_op: PaintCompositeOp, } +#[derive(Clone, Copy, PartialEq, Debug)] +#[repr(C)] +pub struct TileId(pub i32); + +#[derive(Clone, Copy, PartialEq, Debug)] +#[repr(C)] +pub struct FillId(pub i32); + +// TODO(pcwalton): Pack better. #[derive(Clone, Copy, Debug)] -pub struct FillObjectPrimitive { - pub px: LineSegmentU4, - pub subpx: LineSegmentU8, +#[repr(C)] +pub struct TileObjectPrimitive { pub tile_x: i16, pub tile_y: i16, + pub alpha_tile_id: AlphaTileId, + pub path_id: PathId, + // TODO(pcwalton): Maybe look the color up based on path ID? + pub color: u16, + pub ctrl: u8, + pub backdrop: i8, } #[derive(Clone, Copy, Debug)] #[repr(C)] -pub struct TileObjectPrimitive { - pub alpha_tile_id: AlphaTileId, +pub struct TileD3D11 { + pub next_tile_id: TileId, + pub first_fill_id: FillId, + pub alpha_tile_id_lo: i16, + pub alpha_tile_id_hi: i8, + pub backdrop_delta: i8, + pub color: u16, + pub ctrl: u8, pub backdrop: i8, } +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub struct AlphaTileD3D11 { + pub alpha_tile_index: AlphaTileId, + pub clip_tile_index: AlphaTileId, +} + +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub struct TilePathInfoD3D11 { + pub tile_min_x: i16, + pub tile_min_y: i16, + pub tile_max_x: i16, + pub tile_max_y: i16, + pub first_tile_index: u32, + // Must match the order in `TileD3D11`. + pub color: u16, + pub ctrl: u8, + pub backdrop: i8, +} + +// TODO(pcwalton): Pack better! +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] +pub struct PropagateMetadataD3D11 { + pub tile_rect: RectI, + pub tile_offset: u32, + pub path_index: PathBatchIndex, + pub z_write: u32, + // This will generally not refer to the same batch as `path_index`. + pub clip_path_index: PathBatchIndex, + pub backdrop_offset: u32, + pub pad0: u32, + pub pad1: u32, + pub pad2: u32, +} + +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] +pub struct DiceMetadataD3D11 { + pub global_path_id: PathId, + pub first_global_segment_index: u32, + pub first_batch_segment_index: u32, + pub pad: u32, +} + #[derive(Clone, Copy, Debug)] #[repr(C)] pub struct TextureMetadataEntry { pub color_0_transform: Transform2F, + pub color_0_combine_mode: ColorCombineMode, pub base_color: ColorU, + pub filter: Filter, + pub blend_mode: BlendMode, } -#[derive(Clone, Copy, Debug, Default)] -pub struct FillBatchEntry { - pub fill: Fill, - pub page: u16, +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub enum ColorCombineMode { + None, + SrcIn, + DestIn, } #[derive(Clone, Copy, Debug, Default)] #[repr(C)] pub struct Fill { - pub subpx: LineSegmentU8, - pub px: LineSegmentU4, - pub alpha_tile_index: u16, + pub line_segment: LineSegmentU16, + // The meaning of this field depends on whether fills are being done with the GPU rasterizer or + // GPU compute. If raster, this field names the index of the alpha tile that this fill belongs + // to. If compute, this field names the index of the next fill in the singly-linked list of + // fills belonging to this alpha tile. + pub link: u32, } -#[derive(Clone, Debug)] -pub struct ClipBatch { - pub clips: Vec, - pub key: ClipBatchKey, +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub struct ClipMetadata { + pub draw_tile_rect: RectI, + pub clip_tile_rect: RectI, + pub draw_tile_offset: u32, + pub clip_tile_offset: u32, + pub pad0: u32, + pub pad1: u32, } -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct ClipBatchKey { - pub dest_page: u16, - pub src_page: u16, - pub kind: ClipBatchKind, -} - -// Order is significant here. -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum ClipBatchKind { - Draw, - Clip, -} - -#[derive(Clone, Copy, Debug, Default)] +#[derive(Clone, Copy, Debug)] #[repr(C)] pub struct Clip { - pub dest_u: u8, - pub dest_v: u8, - pub src_u: u8, - pub src_v: u8, - pub backdrop: i8, - pub pad_0: u8, - pub pad_1: u16, + pub dest_tile_id: AlphaTileId, + pub dest_backdrop: i32, + pub src_tile_id: AlphaTileId, + pub src_backdrop: i32, } -#[derive(Clone, Copy, Debug, Default)] +impl Default for Clip { + #[inline] + fn default() -> Clip { + Clip { + dest_tile_id: AlphaTileId(!0), + dest_backdrop: 0, + src_tile_id: AlphaTileId(!0), + src_backdrop: 0, + } + } +} + +#[derive(Clone, Copy, Debug)] #[repr(C)] -pub struct Tile { - pub tile_x: i16, - pub tile_y: i16, - pub mask_0_u: u8, - pub mask_0_v: u8, - pub mask_0_backdrop: i8, - pub pad: u8, - pub color: u16, - pub ctrl: u16, +pub struct BinSegment { + pub segment: LineSegment2F, + pub path_index: PathId, + pub pad0: u32, + pub pad1: u32, + pub pad2: u32, +} + +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub struct BackdropInfoD3D11 { + pub initial_backdrop: i32, + // Column number, where 0 is the leftmost column in the tile rect. + pub tile_x_offset: i32, + pub path_index: PathBatchIndex, +} + +#[derive(Clone, Copy)] +#[repr(C)] +pub(crate) struct MicrolineD3D11 { + from_x_px: i16, + from_y_px: i16, + to_x_px: i16, + to_y_px: i16, + from_x_subpx: u8, + from_y_subpx: u8, + to_x_subpx: u8, + to_y_subpx: u8, + path_index: u32, +} + +#[derive(Clone, Copy)] +#[repr(C)] +pub(crate) struct FirstTileD3D11 { + first_tile: i32, } #[derive(Clone, Copy, PartialEq, Debug)] +#[repr(C)] pub struct AlphaTileId(pub u32); +impl PathBatchIndex { + #[inline] + pub fn none() -> PathBatchIndex { + PathBatchIndex(!0) + } +} + impl AlphaTileId { #[inline] pub fn new(next_alpha_tile_index: &[AtomicUsize; ALPHA_TILE_LEVEL_COUNT], level: usize) @@ -249,24 +479,40 @@ impl Debug for RenderCommand { RenderCommand::UploadTextureMetadata(ref metadata) => { write!(formatter, "UploadTextureMetadata(x{})", metadata.len()) } - RenderCommand::AddFills(ref fills) => { - write!(formatter, "AddFills(x{})", fills.len()) + RenderCommand::AddFillsD3D9(ref fills) => { + write!(formatter, "AddFillsD3D9(x{})", fills.len()) } - RenderCommand::FlushFills => write!(formatter, "FlushFills"), - RenderCommand::ClipTiles(ref batches) => { - write!(formatter, "ClipTiles(x{})", batches.len()) + RenderCommand::FlushFillsD3D9 => write!(formatter, "FlushFills"), + RenderCommand::UploadSceneD3D11 { ref draw_segments, ref clip_segments } => { + write!(formatter, + "UploadSceneD3D11(DP x{}, DI x{}, CP x{}, CI x{})", + draw_segments.points.len(), + draw_segments.indices.len(), + clip_segments.points.len(), + clip_segments.indices.len()) + } + RenderCommand::PrepareClipTilesD3D11(ref batch) => { + let clipped_path_count = match batch.clipped_path_info { + None => 0, + Some(ref clipped_path_info) => clipped_path_info.clipped_path_count, + }; + write!(formatter, + "PrepareClipTilesD3D11({:?}, C {})", + batch.batch_id, + clipped_path_count) } RenderCommand::PushRenderTarget(render_target_id) => { write!(formatter, "PushRenderTarget({:?})", render_target_id) } RenderCommand::PopRenderTarget => write!(formatter, "PopRenderTarget"), - RenderCommand::BeginTileDrawing => write!(formatter, "BeginTileDrawing"), - RenderCommand::DrawTiles(ref batch) => { + RenderCommand::DrawTilesD3D9(ref batch) => { + write!(formatter, "DrawTilesD3D9(x{:?})", batch.tiles.len()) + } + RenderCommand::DrawTilesD3D11(ref batch) => { write!(formatter, - "DrawTiles(x{}, C0 {:?}, {:?})", - batch.tiles.len(), - batch.color_texture, - batch.blend_mode) + "DrawTilesD3D11({:?}, C0 {:?})", + batch.tile_batch_data.batch_id, + batch.color_texture) } RenderCommand::Finish { cpu_build_time } => { write!(formatter, "Finish({} ms)", cpu_build_time.as_secs_f64() * 1000.0) @@ -274,3 +520,10 @@ impl Debug for RenderCommand { } } } + +impl Default for FirstTileD3D11 { + #[inline] + fn default() -> FirstTileD3D11 { + FirstTileD3D11 { first_tile: -1 } + } +}