Update `gpu_data`

This commit is contained in:
Patrick Walton 2020-06-23 13:02:15 -07:00
parent eabe1b239d
commit 58a76f0f16
1 changed files with 324 additions and 71 deletions

View File

@ -13,13 +13,15 @@
use crate::builder::{ALPHA_TILES_PER_LEVEL, ALPHA_TILE_LEVEL_COUNT}; use crate::builder::{ALPHA_TILES_PER_LEVEL, ALPHA_TILE_LEVEL_COUNT};
use crate::options::BoundingQuad; use crate::options::BoundingQuad;
use crate::paint::PaintCompositeOp; use crate::paint::PaintCompositeOp;
use crate::scene::PathId;
use crate::tile_map::DenseTileMap;
use pathfinder_color::ColorU; use pathfinder_color::ColorU;
use pathfinder_content::effects::{BlendMode, Filter}; use pathfinder_content::effects::{BlendMode, Filter};
use pathfinder_content::render_target::RenderTargetId; 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::rect::RectI;
use pathfinder_geometry::transform2d::Transform2F; use pathfinder_geometry::transform2d::Transform2F;
use pathfinder_geometry::vector::Vector2I; use pathfinder_geometry::vector::{Vector2F, Vector2I};
use pathfinder_gpu::TextureSamplingFlags; use pathfinder_gpu::TextureSamplingFlags;
use std::fmt::{Debug, Formatter, Result as DebugResult}; use std::fmt::{Debug, Formatter, Result as DebugResult};
use std::sync::Arc; use std::sync::Arc;
@ -64,13 +66,18 @@ pub enum RenderCommand {
UploadTextureMetadata(Vec<TextureMetadataEntry>), UploadTextureMetadata(Vec<TextureMetadataEntry>),
// Adds fills to the queue. // Adds fills to the queue.
AddFills(Vec<FillBatchEntry>), AddFillsD3D9(Vec<Fill>),
// Flushes the queue of fills. // Flushes the queue of fills.
FlushFills, FlushFillsD3D9,
// Renders clips to the mask tile. /// Upload a scene to GPU.
ClipTiles(Vec<ClipBatch>), ///
/// 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 // Pushes a render target onto the stack. Draw commands go to the render target on top of the
// stack. // stack.
@ -79,11 +86,14 @@ pub enum RenderCommand {
// Pops a render target from the stack. // Pops a render target from the stack.
PopRenderTarget, PopRenderTarget,
// Marks that tile compositing is about to begin. // Computes backdrops for tiles, prepares any Z-buffers, and performs clipping.
BeginTileDrawing, PrepareClipTilesD3D11(TileBatchDataD3D11),
// Draws a batch of tiles to the render target on top of the stack. // 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. // Presents a rendered frame.
Finish { cpu_build_time: Duration }, Finish { cpu_build_time: Duration },
@ -103,13 +113,125 @@ pub struct TextureLocation {
pub rect: RectI, pub rect: RectI,
} }
/// Information about a batch of tiles to be prepared (postprocessed).
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct TileBatch { pub struct TileBatchDataD3D11 {
pub tiles: Vec<Tile>, /// 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<ClippedPathInfo>,
}
/// 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<BackdropInfoD3D11>,
/// Mapping from path index to metadata needed to compute propagation on GPU.
///
/// This contains indices into the `tiles` vector.
pub propagate_metadata: Vec<PropagateMetadataD3D11>,
/// Metadata about each path that will be diced (flattened).
pub dice_metadata: Vec<DiceMetadataD3D11>,
/// Sparse information about all the allocated tiles.
pub tile_path_info: Vec<TilePathInfoD3D11>,
/// A transform to apply to the segments.
pub transform: Transform2F,
}
#[derive(Clone, Debug)]
pub struct SegmentsD3D11 {
pub points: Vec<Vector2F>,
pub indices: Vec<SegmentIndicesD3D11>,
}
#[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<Vec<Clip>>,
}
/// 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<TileObjectPrimitive>,
pub clips: Vec<Clip>,
pub z_buffer_data: DenseTileMap<i32>,
/// The color texture to use.
pub color_texture: Option<TileBatchTexture>, pub color_texture: Option<TileBatchTexture>,
/// The filter to use.
pub filter: Filter, pub filter: Filter,
/// The blend mode to composite these tiles with.
pub blend_mode: BlendMode, 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<TileBatchTexture>,
} }
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
@ -119,90 +241,198 @@ pub struct TileBatchTexture {
pub composite_op: PaintCompositeOp, 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)] #[derive(Clone, Copy, Debug)]
pub struct FillObjectPrimitive { #[repr(C)]
pub px: LineSegmentU4, pub struct TileObjectPrimitive {
pub subpx: LineSegmentU8,
pub tile_x: i16, pub tile_x: i16,
pub tile_y: 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)] #[derive(Clone, Copy, Debug)]
#[repr(C)] #[repr(C)]
pub struct TileObjectPrimitive { pub struct TileD3D11 {
pub alpha_tile_id: AlphaTileId, 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, 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)] #[derive(Clone, Copy, Debug)]
#[repr(C)] #[repr(C)]
pub struct TextureMetadataEntry { pub struct TextureMetadataEntry {
pub color_0_transform: Transform2F, pub color_0_transform: Transform2F,
pub color_0_combine_mode: ColorCombineMode,
pub base_color: ColorU, pub base_color: ColorU,
pub filter: Filter,
pub blend_mode: BlendMode,
} }
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug)]
pub struct FillBatchEntry { #[repr(C)]
pub fill: Fill, pub enum ColorCombineMode {
pub page: u16, None,
SrcIn,
DestIn,
} }
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug, Default)]
#[repr(C)] #[repr(C)]
pub struct Fill { pub struct Fill {
pub subpx: LineSegmentU8, pub line_segment: LineSegmentU16,
pub px: LineSegmentU4, // The meaning of this field depends on whether fills are being done with the GPU rasterizer or
pub alpha_tile_index: u16, // 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)] #[derive(Clone, Copy, Debug)]
pub struct ClipBatch { #[repr(C)]
pub clips: Vec<Clip>, pub struct ClipMetadata {
pub key: ClipBatchKey, 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)] #[derive(Clone, Copy, Debug)]
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)]
#[repr(C)] #[repr(C)]
pub struct Clip { pub struct Clip {
pub dest_u: u8, pub dest_tile_id: AlphaTileId,
pub dest_v: u8, pub dest_backdrop: i32,
pub src_u: u8, pub src_tile_id: AlphaTileId,
pub src_v: u8, pub src_backdrop: i32,
pub backdrop: i8,
pub pad_0: u8,
pub pad_1: u16,
} }
#[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)] #[repr(C)]
pub struct Tile { pub struct BinSegment {
pub tile_x: i16, pub segment: LineSegment2F,
pub tile_y: i16, pub path_index: PathId,
pub mask_0_u: u8, pub pad0: u32,
pub mask_0_v: u8, pub pad1: u32,
pub mask_0_backdrop: i8, pub pad2: u32,
pub pad: u8, }
pub color: u16,
pub ctrl: u16, #[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)] #[derive(Clone, Copy, PartialEq, Debug)]
#[repr(C)]
pub struct AlphaTileId(pub u32); pub struct AlphaTileId(pub u32);
impl PathBatchIndex {
#[inline]
pub fn none() -> PathBatchIndex {
PathBatchIndex(!0)
}
}
impl AlphaTileId { impl AlphaTileId {
#[inline] #[inline]
pub fn new(next_alpha_tile_index: &[AtomicUsize; ALPHA_TILE_LEVEL_COUNT], level: usize) 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) => { RenderCommand::UploadTextureMetadata(ref metadata) => {
write!(formatter, "UploadTextureMetadata(x{})", metadata.len()) write!(formatter, "UploadTextureMetadata(x{})", metadata.len())
} }
RenderCommand::AddFills(ref fills) => { RenderCommand::AddFillsD3D9(ref fills) => {
write!(formatter, "AddFills(x{})", fills.len()) write!(formatter, "AddFillsD3D9(x{})", fills.len())
} }
RenderCommand::FlushFills => write!(formatter, "FlushFills"), RenderCommand::FlushFillsD3D9 => write!(formatter, "FlushFills"),
RenderCommand::ClipTiles(ref batches) => { RenderCommand::UploadSceneD3D11 { ref draw_segments, ref clip_segments } => {
write!(formatter, "ClipTiles(x{})", batches.len()) 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) => { RenderCommand::PushRenderTarget(render_target_id) => {
write!(formatter, "PushRenderTarget({:?})", render_target_id) write!(formatter, "PushRenderTarget({:?})", render_target_id)
} }
RenderCommand::PopRenderTarget => write!(formatter, "PopRenderTarget"), RenderCommand::PopRenderTarget => write!(formatter, "PopRenderTarget"),
RenderCommand::BeginTileDrawing => write!(formatter, "BeginTileDrawing"), RenderCommand::DrawTilesD3D9(ref batch) => {
RenderCommand::DrawTiles(ref batch) => { write!(formatter, "DrawTilesD3D9(x{:?})", batch.tiles.len())
}
RenderCommand::DrawTilesD3D11(ref batch) => {
write!(formatter, write!(formatter,
"DrawTiles(x{}, C0 {:?}, {:?})", "DrawTilesD3D11({:?}, C0 {:?})",
batch.tiles.len(), batch.tile_batch_data.batch_id,
batch.color_texture, batch.color_texture)
batch.blend_mode)
} }
RenderCommand::Finish { cpu_build_time } => { RenderCommand::Finish { cpu_build_time } => {
write!(formatter, "Finish({} ms)", cpu_build_time.as_secs_f64() * 1000.0) 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 }
}
}