mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-09 12:21:31 +11:00
Merge pull request #307 from linebender/vello_encoding
vello_encoding crate
This commit is contained in:
commit
3d83bd7fa0
12
Cargo.toml
12
Cargo.toml
|
@ -2,6 +2,7 @@
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
|
"crates/encoding",
|
||||||
"crates/shaders",
|
"crates/shaders",
|
||||||
|
|
||||||
"integrations/vello_svg",
|
"integrations/vello_svg",
|
||||||
|
@ -40,17 +41,20 @@ hot_reload = []
|
||||||
buffer_labels = []
|
buffer_labels = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bytemuck = { workspace = true }
|
||||||
|
fello = { workspace = true }
|
||||||
|
peniko = { workspace = true }
|
||||||
wgpu = { workspace = true }
|
wgpu = { workspace = true }
|
||||||
raw-window-handle = "0.5"
|
raw-window-handle = "0.5"
|
||||||
futures-intrusive = "0.5.0"
|
futures-intrusive = "0.5.0"
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
bytemuck = { version = "1.12.1", features = ["derive"] }
|
|
||||||
smallvec = "1.8.0"
|
smallvec = "1.8.0"
|
||||||
fello = { git = "https://github.com/dfrg/fount", rev = "58a284eaae67512fb61cf76177c5d33238d79cb1" }
|
vello_encoding = { path = "crates/encoding" }
|
||||||
peniko = { git = "https://github.com/linebender/peniko", rev = "cafdac9a211a0fb2fec5656bd663d1ac770bcc81" }
|
|
||||||
guillotiere = "0.6.2"
|
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
|
bytemuck = { version = "1.12.1", features = ["derive"] }
|
||||||
|
fello = { git = "https://github.com/dfrg/fount", rev = "58a284eaae67512fb61cf76177c5d33238d79cb1" }
|
||||||
|
peniko = { git = "https://github.com/linebender/peniko", rev = "cafdac9a211a0fb2fec5656bd663d1ac770bcc81" }
|
||||||
wgpu = "0.15"
|
wgpu = "0.15"
|
||||||
|
|
||||||
# Used for examples
|
# Used for examples
|
||||||
|
|
10
crates/encoding/Cargo.toml
Normal file
10
crates/encoding/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "vello_encoding"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bytemuck = { workspace = true }
|
||||||
|
fello = { workspace = true }
|
||||||
|
peniko = { workspace = true }
|
||||||
|
guillotiere = "0.6.2"
|
12
crates/encoding/src/binning.rs
Normal file
12
crates/encoding/src/binning.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright 2023 The Vello authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
|
||||||
|
use bytemuck::{Pod, Zeroable};
|
||||||
|
|
||||||
|
/// Binning header.
|
||||||
|
#[derive(Copy, Clone, Pod, Zeroable, Debug, Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct BinHeader {
|
||||||
|
pub element_count: u32,
|
||||||
|
pub chunk_offset: u32,
|
||||||
|
}
|
43
crates/encoding/src/clip.rs
Normal file
43
crates/encoding/src/clip.rs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright 2023 The Vello authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
|
||||||
|
use bytemuck::{Pod, Zeroable};
|
||||||
|
|
||||||
|
/// Clip stack element.
|
||||||
|
#[derive(Copy, Clone, Pod, Zeroable, Debug, Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct ClipBic {
|
||||||
|
pub a: u32,
|
||||||
|
pub b: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clip element.
|
||||||
|
#[derive(Copy, Clone, Pod, Zeroable, Debug, Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct ClipElement {
|
||||||
|
pub parent_ix: u32,
|
||||||
|
_padding: [u8; 12],
|
||||||
|
pub bbox: [f32; 4],
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clip resolution.
|
||||||
|
///
|
||||||
|
/// This is an intermediate element used to match clips to associated paths
|
||||||
|
/// and is also used to connect begin and end clip pairs.
|
||||||
|
#[derive(Copy, Clone, Pod, Zeroable, Debug, Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Clip {
|
||||||
|
// Index of the draw object.
|
||||||
|
pub ix: u32,
|
||||||
|
/// This is a packed encoding of an enum with the sign bit as the tag. If positive,
|
||||||
|
/// this entry is a BeginClip and contains the associated path index. If negative,
|
||||||
|
/// it is an EndClip and contains the bitwise-not of the EndClip draw object index.
|
||||||
|
pub path_ix: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clip bounding box.
|
||||||
|
#[derive(Copy, Clone, Pod, Zeroable, Debug, Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct ClipBbox {
|
||||||
|
pub bbox: [f32; 4],
|
||||||
|
}
|
327
crates/encoding/src/config.rs
Normal file
327
crates/encoding/src/config.rs
Normal file
|
@ -0,0 +1,327 @@
|
||||||
|
// Copyright 2023 The Vello authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
BinHeader, Clip, ClipBbox, ClipBic, ClipElement, Cubic, DrawBbox, DrawMonoid, Layout, Path,
|
||||||
|
PathBbox, PathMonoid, PathSegment, Tile,
|
||||||
|
};
|
||||||
|
use bytemuck::{Pod, Zeroable};
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
const TILE_WIDTH: u32 = 16;
|
||||||
|
const TILE_HEIGHT: u32 = 16;
|
||||||
|
|
||||||
|
// TODO: Obtain these from the vello_shaders crate
|
||||||
|
pub(crate) const PATH_REDUCE_WG: u32 = 256;
|
||||||
|
const PATH_BBOX_WG: u32 = 256;
|
||||||
|
const PATH_COARSE_WG: u32 = 256;
|
||||||
|
const CLIP_REDUCE_WG: u32 = 256;
|
||||||
|
|
||||||
|
/// Counters for tracking dynamic allocation on the GPU.
|
||||||
|
///
|
||||||
|
/// This must be kept in sync with the struct in shader/shared/bump.wgsl
|
||||||
|
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct BumpAllocators {
|
||||||
|
pub failed: u32,
|
||||||
|
// Final needed dynamic size of the buffers. If any of these are larger
|
||||||
|
// than the corresponding `_size` element reallocation needs to occur.
|
||||||
|
pub binning: u32,
|
||||||
|
pub ptcl: u32,
|
||||||
|
pub tile: u32,
|
||||||
|
pub segments: u32,
|
||||||
|
pub blend: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Uniform render configuration data used by all GPU stages.
|
||||||
|
///
|
||||||
|
/// This data structure must be kept in sync with the definition in
|
||||||
|
/// shaders/shared/config.wgsl.
|
||||||
|
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct ConfigUniform {
|
||||||
|
/// Width of the scene in tiles.
|
||||||
|
pub width_in_tiles: u32,
|
||||||
|
/// Height of the scene in tiles.
|
||||||
|
pub height_in_tiles: u32,
|
||||||
|
/// Width of the target in pixels.
|
||||||
|
pub target_width: u32,
|
||||||
|
/// Height of the target in pixels.
|
||||||
|
pub target_height: u32,
|
||||||
|
/// The base background color applied to the target before any blends.
|
||||||
|
pub base_color: u32,
|
||||||
|
/// Layout of packed scene data.
|
||||||
|
pub layout: Layout,
|
||||||
|
/// Size of binning buffer allocation (in u32s).
|
||||||
|
pub binning_size: u32,
|
||||||
|
/// Size of tile buffer allocation (in Tiles).
|
||||||
|
pub tiles_size: u32,
|
||||||
|
/// Size of segment buffer allocation (in PathSegments).
|
||||||
|
pub segments_size: u32,
|
||||||
|
/// Size of per-tile command list buffer allocation (in u32s).
|
||||||
|
pub ptcl_size: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// CPU side setup and configuration.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct RenderConfig {
|
||||||
|
/// GPU side configuration.
|
||||||
|
pub gpu: ConfigUniform,
|
||||||
|
/// Workgroup counts for all compute pipelines.
|
||||||
|
pub workgroup_counts: WorkgroupCounts,
|
||||||
|
/// Sizes of all buffer resources.
|
||||||
|
pub buffer_sizes: BufferSizes,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderConfig {
|
||||||
|
pub fn new(layout: &Layout, width: u32, height: u32, base_color: &peniko::Color) -> Self {
|
||||||
|
let new_width = next_multiple_of(width, TILE_WIDTH);
|
||||||
|
let new_height = next_multiple_of(height, TILE_HEIGHT);
|
||||||
|
let width_in_tiles = new_width / TILE_WIDTH;
|
||||||
|
let height_in_tiles = new_height / TILE_HEIGHT;
|
||||||
|
let n_path_tags = layout.path_tags_size();
|
||||||
|
let workgroup_counts =
|
||||||
|
WorkgroupCounts::new(layout, width_in_tiles, height_in_tiles, n_path_tags);
|
||||||
|
let buffer_sizes = BufferSizes::new(layout, &workgroup_counts, n_path_tags);
|
||||||
|
Self {
|
||||||
|
gpu: ConfigUniform {
|
||||||
|
width_in_tiles,
|
||||||
|
height_in_tiles,
|
||||||
|
target_width: width,
|
||||||
|
target_height: height,
|
||||||
|
base_color: base_color.to_premul_u32(),
|
||||||
|
binning_size: buffer_sizes.bin_data.len() - layout.bin_data_start,
|
||||||
|
tiles_size: buffer_sizes.tiles.len(),
|
||||||
|
segments_size: buffer_sizes.segments.len(),
|
||||||
|
ptcl_size: buffer_sizes.ptcl.len(),
|
||||||
|
layout: *layout,
|
||||||
|
},
|
||||||
|
workgroup_counts,
|
||||||
|
buffer_sizes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Type alias for a workgroup size.
|
||||||
|
pub type WorkgroupSize = (u32, u32, u32);
|
||||||
|
|
||||||
|
/// Computed sizes for all dispatches.
|
||||||
|
#[derive(Copy, Clone, Debug, Default)]
|
||||||
|
pub struct WorkgroupCounts {
|
||||||
|
pub use_large_path_scan: bool,
|
||||||
|
pub path_reduce: WorkgroupSize,
|
||||||
|
pub path_reduce2: WorkgroupSize,
|
||||||
|
pub path_scan1: WorkgroupSize,
|
||||||
|
pub path_scan: WorkgroupSize,
|
||||||
|
pub bbox_clear: WorkgroupSize,
|
||||||
|
pub path_seg: WorkgroupSize,
|
||||||
|
pub draw_reduce: WorkgroupSize,
|
||||||
|
pub draw_leaf: WorkgroupSize,
|
||||||
|
pub clip_reduce: WorkgroupSize,
|
||||||
|
pub clip_leaf: WorkgroupSize,
|
||||||
|
pub binning: WorkgroupSize,
|
||||||
|
pub tile_alloc: WorkgroupSize,
|
||||||
|
pub path_coarse: WorkgroupSize,
|
||||||
|
pub backdrop: WorkgroupSize,
|
||||||
|
pub coarse: WorkgroupSize,
|
||||||
|
pub fine: WorkgroupSize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WorkgroupCounts {
|
||||||
|
pub fn new(
|
||||||
|
layout: &Layout,
|
||||||
|
width_in_tiles: u32,
|
||||||
|
height_in_tiles: u32,
|
||||||
|
n_path_tags: u32,
|
||||||
|
) -> Self {
|
||||||
|
let n_paths = layout.n_paths;
|
||||||
|
let n_draw_objects = layout.n_draw_objects;
|
||||||
|
let n_clips = layout.n_clips;
|
||||||
|
let path_tag_padded = align_up(n_path_tags, 4 * PATH_REDUCE_WG);
|
||||||
|
let path_tag_wgs = path_tag_padded / (4 * PATH_REDUCE_WG);
|
||||||
|
let use_large_path_scan = path_tag_wgs > PATH_REDUCE_WG;
|
||||||
|
let reduced_size = if use_large_path_scan {
|
||||||
|
align_up(path_tag_wgs, PATH_REDUCE_WG)
|
||||||
|
} else {
|
||||||
|
path_tag_wgs
|
||||||
|
};
|
||||||
|
let draw_object_wgs = (n_draw_objects + PATH_BBOX_WG - 1) / PATH_BBOX_WG;
|
||||||
|
let path_coarse_wgs = (n_path_tags + PATH_COARSE_WG - 1) / PATH_COARSE_WG;
|
||||||
|
let clip_reduce_wgs = n_clips.saturating_sub(1) / CLIP_REDUCE_WG;
|
||||||
|
let clip_wgs = (n_clips + CLIP_REDUCE_WG - 1) / CLIP_REDUCE_WG;
|
||||||
|
let path_wgs = (n_paths + PATH_BBOX_WG - 1) / PATH_BBOX_WG;
|
||||||
|
let width_in_bins = (width_in_tiles + 15) / 16;
|
||||||
|
let height_in_bins = (height_in_tiles + 15) / 16;
|
||||||
|
Self {
|
||||||
|
use_large_path_scan,
|
||||||
|
path_reduce: (path_tag_wgs, 1, 1),
|
||||||
|
path_reduce2: (PATH_REDUCE_WG, 1, 1),
|
||||||
|
path_scan1: (reduced_size / PATH_REDUCE_WG, 1, 1),
|
||||||
|
path_scan: (path_tag_wgs, 1, 1),
|
||||||
|
bbox_clear: (draw_object_wgs, 1, 1),
|
||||||
|
path_seg: (path_coarse_wgs, 1, 1),
|
||||||
|
draw_reduce: (draw_object_wgs, 1, 1),
|
||||||
|
draw_leaf: (draw_object_wgs, 1, 1),
|
||||||
|
clip_reduce: (clip_reduce_wgs, 1, 1),
|
||||||
|
clip_leaf: (clip_wgs, 1, 1),
|
||||||
|
binning: (draw_object_wgs, 1, 1),
|
||||||
|
tile_alloc: (path_wgs, 1, 1),
|
||||||
|
path_coarse: (path_coarse_wgs, 1, 1),
|
||||||
|
backdrop: (path_wgs, 1, 1),
|
||||||
|
coarse: (width_in_bins, height_in_bins, 1),
|
||||||
|
fine: (width_in_tiles, height_in_tiles, 1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Typed buffer size primitive.
|
||||||
|
#[derive(Copy, Clone, Eq, Default, Debug)]
|
||||||
|
pub struct BufferSize<T: Sized> {
|
||||||
|
len: u32,
|
||||||
|
_phantom: std::marker::PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Sized> BufferSize<T> {
|
||||||
|
/// Creates a new buffer size from number of elements.
|
||||||
|
pub const fn new(len: u32) -> Self {
|
||||||
|
Self {
|
||||||
|
len,
|
||||||
|
_phantom: std::marker::PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new buffer size from size in bytes.
|
||||||
|
pub const fn from_size_in_bytes(size: u32) -> Self {
|
||||||
|
Self::new(size / mem::size_of::<T>() as u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the number of elements.
|
||||||
|
pub const fn len(self) -> u32 {
|
||||||
|
self.len
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the size in bytes.
|
||||||
|
pub const fn size_in_bytes(self) -> u32 {
|
||||||
|
mem::size_of::<T>() as u32 * self.len
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the size in bytes aligned up to the given value.
|
||||||
|
pub const fn aligned_in_bytes(self, alignment: u32) -> u32 {
|
||||||
|
align_up(self.size_in_bytes(), alignment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Sized> PartialEq for BufferSize<T> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.len == other.len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Sized> PartialOrd for BufferSize<T> {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
|
self.len.partial_cmp(&other.len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computed sizes for all buffers.
|
||||||
|
#[derive(Copy, Clone, Debug, Default)]
|
||||||
|
pub struct BufferSizes {
|
||||||
|
// Known size buffers
|
||||||
|
pub path_reduced: BufferSize<PathMonoid>,
|
||||||
|
pub path_reduced2: BufferSize<PathMonoid>,
|
||||||
|
pub path_reduced_scan: BufferSize<PathMonoid>,
|
||||||
|
pub path_monoids: BufferSize<PathMonoid>,
|
||||||
|
pub path_bboxes: BufferSize<PathBbox>,
|
||||||
|
pub cubics: BufferSize<Cubic>,
|
||||||
|
pub draw_reduced: BufferSize<DrawMonoid>,
|
||||||
|
pub draw_monoids: BufferSize<DrawMonoid>,
|
||||||
|
pub info: BufferSize<u32>,
|
||||||
|
pub clip_inps: BufferSize<Clip>,
|
||||||
|
pub clip_els: BufferSize<ClipElement>,
|
||||||
|
pub clip_bics: BufferSize<ClipBic>,
|
||||||
|
pub clip_bboxes: BufferSize<ClipBbox>,
|
||||||
|
pub draw_bboxes: BufferSize<DrawBbox>,
|
||||||
|
pub bump_alloc: BufferSize<BumpAllocators>,
|
||||||
|
pub bin_headers: BufferSize<BinHeader>,
|
||||||
|
pub paths: BufferSize<Path>,
|
||||||
|
// Bump allocated buffers
|
||||||
|
pub bin_data: BufferSize<u32>,
|
||||||
|
pub tiles: BufferSize<Tile>,
|
||||||
|
pub segments: BufferSize<PathSegment>,
|
||||||
|
pub ptcl: BufferSize<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BufferSizes {
|
||||||
|
pub fn new(layout: &Layout, workgroups: &WorkgroupCounts, n_path_tags: u32) -> Self {
|
||||||
|
let n_paths = layout.n_paths;
|
||||||
|
let n_draw_objects = layout.n_draw_objects;
|
||||||
|
let n_clips = layout.n_clips;
|
||||||
|
let path_tag_wgs = workgroups.path_reduce.0;
|
||||||
|
let reduced_size = if workgroups.use_large_path_scan {
|
||||||
|
align_up(path_tag_wgs, PATH_REDUCE_WG)
|
||||||
|
} else {
|
||||||
|
path_tag_wgs
|
||||||
|
};
|
||||||
|
let path_reduced = BufferSize::new(reduced_size);
|
||||||
|
let path_reduced2 = BufferSize::new(PATH_REDUCE_WG);
|
||||||
|
let path_reduced_scan = BufferSize::new(path_tag_wgs);
|
||||||
|
let path_monoids = BufferSize::new(path_tag_wgs * PATH_REDUCE_WG);
|
||||||
|
let path_bboxes = BufferSize::new(n_paths);
|
||||||
|
let cubics = BufferSize::new(n_path_tags);
|
||||||
|
let draw_object_wgs = workgroups.draw_reduce.0;
|
||||||
|
let draw_reduced = BufferSize::new(draw_object_wgs);
|
||||||
|
let draw_monoids = BufferSize::new(n_draw_objects);
|
||||||
|
let info = BufferSize::new(layout.bin_data_start);
|
||||||
|
let clip_inps = BufferSize::new(n_clips);
|
||||||
|
let clip_els = BufferSize::new(n_clips);
|
||||||
|
let clip_bics = BufferSize::new(n_clips / CLIP_REDUCE_WG);
|
||||||
|
let clip_bboxes = BufferSize::new(n_clips);
|
||||||
|
let draw_bboxes = BufferSize::new(n_paths);
|
||||||
|
let bump_alloc = BufferSize::new(1);
|
||||||
|
let bin_headers = BufferSize::new(draw_object_wgs * 256);
|
||||||
|
let n_paths_aligned = align_up(n_paths, 256);
|
||||||
|
let paths = BufferSize::new(n_paths_aligned);
|
||||||
|
|
||||||
|
// The following buffer sizes have been hand picked to accommodate the vello test scenes as
|
||||||
|
// well as paris-30k. These should instead get derived from the scene layout using
|
||||||
|
// reasonable heuristics.
|
||||||
|
let bin_data = BufferSize::new(1 << 18);
|
||||||
|
let tiles = BufferSize::new(1 << 21);
|
||||||
|
let segments = BufferSize::new(1 << 21);
|
||||||
|
let ptcl = BufferSize::new(1 << 23);
|
||||||
|
Self {
|
||||||
|
path_reduced,
|
||||||
|
path_reduced2,
|
||||||
|
path_reduced_scan,
|
||||||
|
path_monoids,
|
||||||
|
path_bboxes,
|
||||||
|
cubics,
|
||||||
|
draw_reduced,
|
||||||
|
draw_monoids,
|
||||||
|
info,
|
||||||
|
clip_inps,
|
||||||
|
clip_els,
|
||||||
|
clip_bics,
|
||||||
|
clip_bboxes,
|
||||||
|
draw_bboxes,
|
||||||
|
bump_alloc,
|
||||||
|
bin_headers,
|
||||||
|
paths,
|
||||||
|
bin_data,
|
||||||
|
tiles,
|
||||||
|
segments,
|
||||||
|
ptcl,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn align_up(len: u32, alignment: u32) -> u32 {
|
||||||
|
len + (len.wrapping_neg() & (alignment - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn next_multiple_of(val: u32, rhs: u32) -> u32 {
|
||||||
|
match val % rhs {
|
||||||
|
0 => val,
|
||||||
|
r => val + (rhs - r),
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +1,5 @@
|
||||||
// Copyright 2022 Google LLC
|
// Copyright 2022 The Vello authors
|
||||||
//
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Also licensed under MIT license, at your choice.
|
|
||||||
|
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use peniko::{BlendMode, Color};
|
use peniko::{BlendMode, Color};
|
||||||
|
@ -54,6 +41,13 @@ impl DrawTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draw object bounding box.
|
||||||
|
#[derive(Copy, Clone, Pod, Zeroable, Debug, Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct DrawBbox {
|
||||||
|
pub bbox: [f32; 4],
|
||||||
|
}
|
||||||
|
|
||||||
/// Draw data for a solid color.
|
/// Draw data for a solid color.
|
||||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -131,7 +125,7 @@ impl DrawBeginClip {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Monoid for the draw tag stream.
|
/// Monoid for the draw tag stream.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Pod, Zeroable, Default)]
|
#[derive(Copy, Clone, PartialEq, Eq, Pod, Zeroable, Default, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct DrawMonoid {
|
pub struct DrawMonoid {
|
||||||
// The number of paths preceding this draw object.
|
// The number of paths preceding this draw object.
|
|
@ -1,24 +1,9 @@
|
||||||
// Copyright 2022 Google LLC
|
// Copyright 2022 The Vello authors
|
||||||
//
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Also licensed under MIT license, at your choice.
|
|
||||||
|
|
||||||
use crate::encoding::DrawImage;
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
resolve::Patch, DrawColor, DrawLinearGradient, DrawRadialGradient, DrawTag, Glyph, GlyphRun,
|
resolve::Patch, DrawColor, DrawImage, DrawLinearGradient, DrawRadialGradient, DrawTag, Glyph,
|
||||||
PathEncoder, PathTag, Transform,
|
GlyphRun, PathEncoder, PathTag, Transform,
|
||||||
};
|
};
|
||||||
|
|
||||||
use fello::NormalizedCoord;
|
use fello::NormalizedCoord;
|
||||||
|
@ -170,9 +155,7 @@ impl Encoding {
|
||||||
linewidths: self.linewidths.len(),
|
linewidths: self.linewidths.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Encoding {
|
|
||||||
/// Encodes a linewidth.
|
/// Encodes a linewidth.
|
||||||
pub fn encode_linewidth(&mut self, linewidth: f32) {
|
pub fn encode_linewidth(&mut self, linewidth: f32) {
|
||||||
if self.linewidths.last() != Some(&linewidth) {
|
if self.linewidths.last() != Some(&linewidth) {
|
|
@ -1,18 +1,5 @@
|
||||||
// Copyright 2022 Google LLC
|
// Copyright 2023 The Vello authors
|
||||||
//
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Also licensed under MIT license, at your choice.
|
|
||||||
|
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
|
@ -1,18 +1,5 @@
|
||||||
// Copyright 2022 Google LLC
|
// Copyright 2022 The Vello authors
|
||||||
//
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Also licensed under MIT license, at your choice.
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
@ -59,11 +46,11 @@ impl GlyphCache {
|
||||||
Style::Fill(Fill::EvenOdd) => encoding_cache.encode_linewidth(-2.0),
|
Style::Fill(Fill::EvenOdd) => encoding_cache.encode_linewidth(-2.0),
|
||||||
Style::Stroke(stroke) => encoding_cache.encode_linewidth(stroke.width),
|
Style::Stroke(stroke) => encoding_cache.encode_linewidth(stroke.width),
|
||||||
}
|
}
|
||||||
let mut path = crate::glyph::PathEncoderPen(encoding_cache.encode_path(is_fill));
|
let mut path = encoding_cache.encode_path(is_fill);
|
||||||
scaler
|
scaler
|
||||||
.outline(GlyphId::new(key.glyph_id as u16), &mut path)
|
.outline(GlyphId::new(key.glyph_id as u16), &mut path)
|
||||||
.ok()?;
|
.ok()?;
|
||||||
if path.0.finish(false) == 0 {
|
if path.finish(false) == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let end = encoding_cache.stream_offsets();
|
let end = encoding_cache.stream_offsets();
|
|
@ -1,18 +1,5 @@
|
||||||
// Copyright 2022 Google LLC
|
// Copyright 2022 The Vello authors
|
||||||
//
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Also licensed under MIT license, at your choice.
|
|
||||||
|
|
||||||
use guillotiere::{size2, AtlasAllocator};
|
use guillotiere::{size2, AtlasAllocator};
|
||||||
use peniko::Image;
|
use peniko::Image;
|
38
crates/encoding/src/lib.rs
Normal file
38
crates/encoding/src/lib.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright 2023 The Vello authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
|
||||||
|
//! Raw scene encoding.
|
||||||
|
|
||||||
|
mod binning;
|
||||||
|
mod clip;
|
||||||
|
mod config;
|
||||||
|
mod draw;
|
||||||
|
mod encoding;
|
||||||
|
mod glyph;
|
||||||
|
mod glyph_cache;
|
||||||
|
mod image_cache;
|
||||||
|
mod math;
|
||||||
|
mod monoid;
|
||||||
|
mod path;
|
||||||
|
mod ramp_cache;
|
||||||
|
mod resolve;
|
||||||
|
|
||||||
|
pub use binning::BinHeader;
|
||||||
|
pub use clip::{Clip, ClipBbox, ClipBic, ClipElement};
|
||||||
|
pub use config::{
|
||||||
|
BufferSize, BufferSizes, BumpAllocators, ConfigUniform, RenderConfig, WorkgroupCounts,
|
||||||
|
WorkgroupSize,
|
||||||
|
};
|
||||||
|
pub use draw::{
|
||||||
|
DrawBbox, DrawBeginClip, DrawColor, DrawImage, DrawLinearGradient, DrawMonoid,
|
||||||
|
DrawRadialGradient, DrawTag,
|
||||||
|
};
|
||||||
|
pub use encoding::{Encoding, StreamOffsets};
|
||||||
|
pub use glyph::{Glyph, GlyphRun};
|
||||||
|
pub use math::Transform;
|
||||||
|
pub use monoid::Monoid;
|
||||||
|
pub use path::{
|
||||||
|
Cubic, Path, PathBbox, PathEncoder, PathMonoid, PathSegment, PathSegmentType, PathTag, Tile,
|
||||||
|
};
|
||||||
|
pub use ramp_cache::Ramps;
|
||||||
|
pub use resolve::{Layout, Patch, Resolver};
|
|
@ -1,18 +1,5 @@
|
||||||
// Copyright 2022 Google LLC
|
// Copyright 2022 The Vello authors
|
||||||
//
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Also licensed under MIT license, at your choice.
|
|
||||||
|
|
||||||
use std::ops::Mul;
|
use std::ops::Mul;
|
||||||
|
|
15
crates/encoding/src/monoid.rs
Normal file
15
crates/encoding/src/monoid.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2022 The Vello authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
|
||||||
|
/// Interface for a monoid. The default value must be the identity of
|
||||||
|
/// the monoid.
|
||||||
|
pub trait Monoid: Default {
|
||||||
|
/// The source value for constructing the monoid.
|
||||||
|
type SourceValue;
|
||||||
|
|
||||||
|
/// Creates a monoid from a given value.
|
||||||
|
fn new(value: Self::SourceValue) -> Self;
|
||||||
|
|
||||||
|
/// Combines two monoids. This operation must be associative.
|
||||||
|
fn combine(&self, other: &Self) -> Self;
|
||||||
|
}
|
|
@ -1,18 +1,5 @@
|
||||||
// Copyright 2022 Google LLC
|
// Copyright 2022 The Vello authors
|
||||||
//
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Also licensed under MIT license, at your choice.
|
|
||||||
|
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use peniko::kurbo::Shape;
|
use peniko::kurbo::Shape;
|
||||||
|
@ -20,7 +7,7 @@ use peniko::kurbo::Shape;
|
||||||
use super::Monoid;
|
use super::Monoid;
|
||||||
|
|
||||||
/// Path segment.
|
/// Path segment.
|
||||||
#[derive(Clone, Copy, Debug, Zeroable, Pod)]
|
#[derive(Clone, Copy, Debug, Zeroable, Pod, Default)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct PathSegment {
|
pub struct PathSegment {
|
||||||
pub origin: [f32; 2],
|
pub origin: [f32; 2],
|
||||||
|
@ -170,6 +157,19 @@ impl Monoid for PathMonoid {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Cubic path segment.
|
||||||
|
#[derive(Copy, Clone, Pod, Zeroable, Debug, Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Cubic {
|
||||||
|
pub p0: [f32; 2],
|
||||||
|
pub p1: [f32; 2],
|
||||||
|
pub p2: [f32; 2],
|
||||||
|
pub p3: [f32; 2],
|
||||||
|
pub stroke: [f32; 2],
|
||||||
|
pub path_ix: u32,
|
||||||
|
pub flags: u32,
|
||||||
|
}
|
||||||
|
|
||||||
/// Path bounding box.
|
/// Path bounding box.
|
||||||
#[derive(Copy, Clone, Pod, Zeroable, Default, Debug)]
|
#[derive(Copy, Clone, Pod, Zeroable, Default, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -188,6 +188,27 @@ pub struct PathBbox {
|
||||||
pub trans_ix: u32,
|
pub trans_ix: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tiled path object.
|
||||||
|
#[derive(Copy, Clone, Pod, Zeroable, Debug, Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Path {
|
||||||
|
/// Bounding box in tiles.
|
||||||
|
pub bbox: [f32; 4],
|
||||||
|
/// Offset (in u32s) to tile rectangle.
|
||||||
|
pub tiles: u32,
|
||||||
|
_padding: [u32; 3],
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tile object.
|
||||||
|
#[derive(Copy, Clone, Pod, Zeroable, Debug, Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Tile {
|
||||||
|
/// Accumulated backdrop at the left edge of the tile.
|
||||||
|
pub backdrop: i32,
|
||||||
|
/// Index of first path segment.
|
||||||
|
pub segments: u32,
|
||||||
|
}
|
||||||
|
|
||||||
/// Encoder for path segments.
|
/// Encoder for path segments.
|
||||||
pub struct PathEncoder<'a> {
|
pub struct PathEncoder<'a> {
|
||||||
tags: &'a mut Vec<PathTag>,
|
tags: &'a mut Vec<PathTag>,
|
||||||
|
@ -381,3 +402,25 @@ impl<'a> PathEncoder<'a> {
|
||||||
self.n_encoded_segments
|
self.n_encoded_segments
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fello::scale::Pen for PathEncoder<'_> {
|
||||||
|
fn move_to(&mut self, x: f32, y: f32) {
|
||||||
|
self.move_to(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn line_to(&mut self, x: f32, y: f32) {
|
||||||
|
self.line_to(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quad_to(&mut self, cx0: f32, cy0: f32, x: f32, y: f32) {
|
||||||
|
self.quad_to(cx0, cy0, x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn curve_to(&mut self, cx0: f32, cy0: f32, cx1: f32, cy1: f32, x: f32, y: f32) {
|
||||||
|
self.cubic_to(cx0, cy0, cx1, cy1, x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close(&mut self) {
|
||||||
|
self.close()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +1,5 @@
|
||||||
// Copyright 2022 Google LLC
|
// Copyright 2022 The Vello authors
|
||||||
//
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Also licensed under MIT license, at your choice.
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
|
@ -1,18 +1,5 @@
|
||||||
// Copyright 2022 Google LLC
|
// Copyright 2022 The Vello authors
|
||||||
//
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Also licensed under MIT license, at your choice.
|
|
||||||
|
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
|
@ -25,7 +12,6 @@ use super::{
|
||||||
ramp_cache::{RampCache, Ramps},
|
ramp_cache::{RampCache, Ramps},
|
||||||
DrawTag, Encoding, PathTag, StreamOffsets, Transform,
|
DrawTag, Encoding, PathTag, StreamOffsets, Transform,
|
||||||
};
|
};
|
||||||
use crate::shaders;
|
|
||||||
|
|
||||||
/// Layout of a packed encoding.
|
/// Layout of a packed encoding.
|
||||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
||||||
|
@ -66,6 +52,12 @@ impl Layout {
|
||||||
bytemuck::cast_slice(&data[start..end])
|
bytemuck::cast_slice(&data[start..end])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn path_tags_size(&self) -> u32 {
|
||||||
|
let start = self.path_tag_base * 4;
|
||||||
|
let end = self.path_data_base * 4;
|
||||||
|
end - start
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the path tag stream in chunks of 4.
|
/// Returns the path tag stream in chunks of 4.
|
||||||
pub fn path_tags_chunked<'a>(&self, data: &'a [u8]) -> &'a [u32] {
|
pub fn path_tags_chunked<'a>(&self, data: &'a [u8]) -> &'a [u32] {
|
||||||
let start = self.path_tag_base as usize * 4;
|
let start = self.path_tag_base as usize * 4;
|
||||||
|
@ -108,35 +100,6 @@ impl Layout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scene configuration.
|
|
||||||
///
|
|
||||||
/// This data structure must be kept in sync with the definition in
|
|
||||||
/// shaders/shared/config.wgsl.
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct Config {
|
|
||||||
/// Width of the scene in tiles.
|
|
||||||
pub width_in_tiles: u32,
|
|
||||||
/// Height of the scene in tiles.
|
|
||||||
pub height_in_tiles: u32,
|
|
||||||
/// Width of the target in pixels.
|
|
||||||
pub target_width: u32,
|
|
||||||
/// Height of the target in pixels.
|
|
||||||
pub target_height: u32,
|
|
||||||
/// The base background color applied to the target before any blends.
|
|
||||||
pub base_color: u32,
|
|
||||||
/// Layout of packed scene data.
|
|
||||||
pub layout: Layout,
|
|
||||||
/// Size of binning buffer allocation (in u32s).
|
|
||||||
pub binning_size: u32,
|
|
||||||
/// Size of tile buffer allocation (in Tiles).
|
|
||||||
pub tiles_size: u32,
|
|
||||||
/// Size of segment buffer allocation (in PathSegments).
|
|
||||||
pub segments_size: u32,
|
|
||||||
/// Size of per-tile command list buffer allocation (in u32s).
|
|
||||||
pub ptcl_size: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resolver for late bound resources.
|
/// Resolver for late bound resources.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Resolver {
|
pub struct Resolver {
|
||||||
|
@ -166,13 +129,15 @@ impl Resolver {
|
||||||
self.resolve_pending_images();
|
self.resolve_pending_images();
|
||||||
let data = packed;
|
let data = packed;
|
||||||
data.clear();
|
data.clear();
|
||||||
let mut layout = Layout::default();
|
let mut layout = Layout {
|
||||||
layout.n_paths = encoding.n_paths;
|
n_paths: encoding.n_paths,
|
||||||
layout.n_clips = encoding.n_clips;
|
n_clips: encoding.n_clips,
|
||||||
|
..Layout::default()
|
||||||
|
};
|
||||||
// Compute size of data buffer
|
// Compute size of data buffer
|
||||||
let n_path_tags =
|
let n_path_tags =
|
||||||
encoding.path_tags.len() + sizes.path_tags + encoding.n_open_clips as usize;
|
encoding.path_tags.len() + sizes.path_tags + encoding.n_open_clips as usize;
|
||||||
let path_tag_padded = align_up(n_path_tags, 4 * shaders::PATHTAG_REDUCE_WG);
|
let path_tag_padded = align_up(n_path_tags, 4 * crate::config::PATH_REDUCE_WG);
|
||||||
let capacity = path_tag_padded
|
let capacity = path_tag_padded
|
||||||
+ slice_size_in_bytes(&encoding.path_data, sizes.path_data)
|
+ slice_size_in_bytes(&encoding.path_data, sizes.path_data)
|
||||||
+ slice_size_in_bytes(
|
+ slice_size_in_bytes(
|
|
@ -17,10 +17,9 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use vello::{
|
use vello::{
|
||||||
encoding::Glyph,
|
|
||||||
fello::meta::MetadataProvider,
|
fello::meta::MetadataProvider,
|
||||||
fello::raw::FontRef,
|
fello::raw::FontRef,
|
||||||
glyph::GlyphContext,
|
glyph::{Glyph, GlyphContext},
|
||||||
kurbo::Affine,
|
kurbo::Affine,
|
||||||
peniko::{Blob, Brush, BrushRef, Font, StyleRef},
|
peniko::{Blob, Brush, BrushRef, Font, StyleRef},
|
||||||
SceneBuilder,
|
SceneBuilder,
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
// Copyright 2022 Google LLC
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Also licensed under MIT license, at your choice.
|
|
||||||
|
|
||||||
//! Raw scene encoding.
|
|
||||||
|
|
||||||
mod draw;
|
|
||||||
mod encoding;
|
|
||||||
mod glyph;
|
|
||||||
mod glyph_cache;
|
|
||||||
mod image_cache;
|
|
||||||
mod math;
|
|
||||||
mod monoid;
|
|
||||||
mod path;
|
|
||||||
mod ramp_cache;
|
|
||||||
mod resolve;
|
|
||||||
|
|
||||||
pub use draw::{
|
|
||||||
DrawBeginClip, DrawColor, DrawImage, DrawLinearGradient, DrawMonoid, DrawRadialGradient,
|
|
||||||
DrawTag,
|
|
||||||
};
|
|
||||||
pub use encoding::{Encoding, StreamOffsets};
|
|
||||||
pub use glyph::{Glyph, GlyphRun};
|
|
||||||
pub use math::Transform;
|
|
||||||
pub use monoid::Monoid;
|
|
||||||
pub use path::{PathBbox, PathEncoder, PathMonoid, PathSegment, PathSegmentType, PathTag};
|
|
||||||
pub use ramp_cache::Ramps;
|
|
||||||
pub use resolve::{Config, Layout, Patch, Resolver};
|
|
|
@ -1,28 +0,0 @@
|
||||||
// Copyright 2022 Google LLC
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Also licensed under MIT license, at your choice.
|
|
||||||
|
|
||||||
/// Interface for a monoid. The default value must be the identity of
|
|
||||||
/// the monoid.
|
|
||||||
pub trait Monoid: Default {
|
|
||||||
/// The source value for constructing the monoid.
|
|
||||||
type SourceValue;
|
|
||||||
|
|
||||||
/// Creates a monoid from a given value.
|
|
||||||
fn new(value: Self::SourceValue) -> Self;
|
|
||||||
|
|
||||||
/// Combines two monoids. This operation must be associative.
|
|
||||||
fn combine(&self, other: &Self) -> Self;
|
|
||||||
}
|
|
|
@ -330,7 +330,7 @@ impl Engine {
|
||||||
let format = proxy.format.to_wgpu();
|
let format = proxy.format.to_wgpu();
|
||||||
queue.write_texture(
|
queue.write_texture(
|
||||||
wgpu::ImageCopyTexture {
|
wgpu::ImageCopyTexture {
|
||||||
texture: &texture,
|
texture,
|
||||||
mip_level: 0,
|
mip_level: 0,
|
||||||
origin: wgpu::Origin3d { x: *x, y: *y, z: 0 },
|
origin: wgpu::Origin3d { x: *x, y: *y, z: 0 },
|
||||||
aspect: TextureAspect::All,
|
aspect: TextureAspect::All,
|
||||||
|
|
51
src/glyph.rs
51
src/glyph.rs
|
@ -16,20 +16,21 @@
|
||||||
|
|
||||||
//! Support for glyph rendering.
|
//! Support for glyph rendering.
|
||||||
|
|
||||||
use fello::scale::Pen;
|
|
||||||
|
|
||||||
use crate::encoding::{Encoding, PathEncoder};
|
|
||||||
use crate::scene::{SceneBuilder, SceneFragment};
|
use crate::scene::{SceneBuilder, SceneFragment};
|
||||||
use peniko::kurbo::Affine;
|
use {
|
||||||
use peniko::{Brush, Color, Fill, Style};
|
fello::{
|
||||||
|
raw::types::GlyphId,
|
||||||
use fello::{
|
raw::FontRef,
|
||||||
raw::types::GlyphId,
|
scale::{Context, Pen, Scaler},
|
||||||
raw::FontRef,
|
FontKey, Setting, Size,
|
||||||
scale::{Context, Scaler},
|
},
|
||||||
FontKey, Setting, Size,
|
peniko::kurbo::Affine,
|
||||||
|
peniko::{Brush, Color, Fill, Style},
|
||||||
|
vello_encoding::Encoding,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub use vello_encoding::Glyph;
|
||||||
|
|
||||||
/// General context for creating scene fragments for glyph outlines.
|
/// General context for creating scene fragments for glyph outlines.
|
||||||
pub struct GlyphContext {
|
pub struct GlyphContext {
|
||||||
ctx: Context,
|
ctx: Context,
|
||||||
|
@ -105,9 +106,9 @@ impl<'a> GlyphProvider<'a> {
|
||||||
Style::Fill(Fill::EvenOdd) => encoding.encode_linewidth(-2.0),
|
Style::Fill(Fill::EvenOdd) => encoding.encode_linewidth(-2.0),
|
||||||
Style::Stroke(stroke) => encoding.encode_linewidth(stroke.width),
|
Style::Stroke(stroke) => encoding.encode_linewidth(stroke.width),
|
||||||
}
|
}
|
||||||
let mut path = PathEncoderPen(encoding.encode_path(matches!(style, Style::Fill(_))));
|
let mut path = encoding.encode_path(matches!(style, Style::Fill(_)));
|
||||||
self.scaler.outline(GlyphId::new(gid), &mut path).ok()?;
|
self.scaler.outline(GlyphId::new(gid), &mut path).ok()?;
|
||||||
if path.0.finish(false) != 0 {
|
if path.finish(false) != 0 {
|
||||||
Some(())
|
Some(())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -144,27 +145,3 @@ impl Pen for BezPathPen {
|
||||||
self.0.close_path()
|
self.0.close_path()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct PathEncoderPen<'a>(pub PathEncoder<'a>);
|
|
||||||
|
|
||||||
impl Pen for PathEncoderPen<'_> {
|
|
||||||
fn move_to(&mut self, x: f32, y: f32) {
|
|
||||||
self.0.move_to(x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn line_to(&mut self, x: f32, y: f32) {
|
|
||||||
self.0.line_to(x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn quad_to(&mut self, cx0: f32, cy0: f32, x: f32, y: f32) {
|
|
||||||
self.0.quad_to(cx0, cy0, x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn curve_to(&mut self, cx0: f32, cy0: f32, cx1: f32, cy1: f32, x: f32, y: f32) {
|
|
||||||
self.0.cubic_to(cx0, cy0, cx1, cy1, x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn close(&mut self) {
|
|
||||||
self.0.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -27,8 +27,6 @@ pub use peniko::kurbo;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use fello;
|
pub use fello;
|
||||||
|
|
||||||
pub mod encoding;
|
|
||||||
|
|
||||||
pub mod glyph;
|
pub mod glyph;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
|
@ -138,7 +136,7 @@ impl Renderer {
|
||||||
if target.width != width || target.height != height {
|
if target.width != width || target.height != height {
|
||||||
target = TargetTexture::new(device, width, height);
|
target = TargetTexture::new(device, width, height);
|
||||||
}
|
}
|
||||||
self.render_to_texture(device, queue, scene, &target.view, ¶ms)?;
|
self.render_to_texture(device, queue, scene, &target.view, params)?;
|
||||||
let blit = self
|
let blit = self
|
||||||
.blit
|
.blit
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
|
343
src/render.rs
343
src/render.rs
|
@ -1,27 +1,16 @@
|
||||||
//! Take an encoded scene and create a graph to render it
|
//! Take an encoded scene and create a graph to render it
|
||||||
|
|
||||||
use bytemuck::{Pod, Zeroable};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
encoding::{Config, Encoding, Layout},
|
|
||||||
engine::{BufProxy, ImageFormat, ImageProxy, Recording, ResourceProxy},
|
engine::{BufProxy, ImageFormat, ImageProxy, Recording, ResourceProxy},
|
||||||
shaders::{self, FullShaders, Shaders},
|
shaders::{self, FullShaders},
|
||||||
RenderParams, Scene,
|
RenderParams, Scene,
|
||||||
};
|
};
|
||||||
|
use vello_encoding::{Encoding, WorkgroupSize};
|
||||||
|
|
||||||
/// State for a render in progress.
|
/// State for a render in progress.
|
||||||
pub struct Render {
|
pub struct Render {
|
||||||
/// Size of binning and info combined buffer in u32 units
|
fine_wg_count: Option<WorkgroupSize>,
|
||||||
binning_info_size: u32,
|
fine_resources: Option<FineResources>,
|
||||||
/// Size of tiles buf in tiles
|
|
||||||
tiles_size: u32,
|
|
||||||
/// Size of segments buf in segments
|
|
||||||
segments_size: u32,
|
|
||||||
/// Size of per-tile command list in u32 units
|
|
||||||
ptcl_size: u32,
|
|
||||||
width_in_tiles: u32,
|
|
||||||
height_in_tiles: u32,
|
|
||||||
fine: Option<FineResources>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resources produced by pipeline, needed for fine rasterization.
|
/// Resources produced by pipeline, needed for fine rasterization.
|
||||||
|
@ -38,128 +27,6 @@ struct FineResources {
|
||||||
out_image: ImageProxy,
|
out_image: ImageProxy,
|
||||||
}
|
}
|
||||||
|
|
||||||
const TAG_MONOID_SIZE: u64 = 12;
|
|
||||||
const TAG_MONOID_FULL_SIZE: u64 = 20;
|
|
||||||
const PATH_BBOX_SIZE: u64 = 24;
|
|
||||||
const CUBIC_SIZE: u64 = 48;
|
|
||||||
const DRAWMONOID_SIZE: u64 = 16;
|
|
||||||
const CLIP_BIC_SIZE: u64 = 8;
|
|
||||||
const CLIP_EL_SIZE: u64 = 32;
|
|
||||||
const CLIP_INP_SIZE: u64 = 8;
|
|
||||||
const CLIP_BBOX_SIZE: u64 = 16;
|
|
||||||
const PATH_SIZE: u64 = 32;
|
|
||||||
const DRAW_BBOX_SIZE: u64 = 16;
|
|
||||||
const BUMP_SIZE: u64 = std::mem::size_of::<BumpAllocators>() as u64;
|
|
||||||
const BIN_HEADER_SIZE: u64 = 8;
|
|
||||||
const TILE_SIZE: u64 = 8;
|
|
||||||
const SEGMENT_SIZE: u64 = 24;
|
|
||||||
|
|
||||||
fn size_to_words(byte_size: usize) -> u32 {
|
|
||||||
(byte_size / std::mem::size_of::<u32>()) as u32
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn next_multiple_of(val: u32, rhs: u32) -> u32 {
|
|
||||||
match val % rhs {
|
|
||||||
0 => val,
|
|
||||||
r => val + (rhs - r),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This must be kept in sync with the struct in shader/shared/bump.wgsl
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
|
||||||
struct BumpAllocators {
|
|
||||||
failed: u32,
|
|
||||||
// Final needed dynamic size of the buffers. If any of these are larger than the corresponding `_size` element
|
|
||||||
// reallocation needs to occur
|
|
||||||
binning: u32,
|
|
||||||
ptcl: u32,
|
|
||||||
tile: u32,
|
|
||||||
segments: u32,
|
|
||||||
blend: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
fn render(scene: &Scene, shaders: &Shaders) -> (Recording, BufProxy) {
|
|
||||||
let mut recording = Recording::default();
|
|
||||||
let data = scene.data();
|
|
||||||
let n_pathtag = data.path_tags.len();
|
|
||||||
let pathtag_padded = align_up(n_pathtag, 4 * shaders::PATHTAG_REDUCE_WG);
|
|
||||||
let pathtag_wgs = pathtag_padded / (4 * shaders::PATHTAG_REDUCE_WG as usize);
|
|
||||||
let mut scene: Vec<u8> = Vec::with_capacity(pathtag_padded);
|
|
||||||
let pathtag_base = size_to_words(scene.len());
|
|
||||||
scene.extend(bytemuck::cast_slice(&data.path_tags));
|
|
||||||
scene.resize(pathtag_padded, 0);
|
|
||||||
let pathdata_base = size_to_words(scene.len());
|
|
||||||
scene.extend(&data.path_data);
|
|
||||||
|
|
||||||
let config = Config {
|
|
||||||
width_in_tiles: 64,
|
|
||||||
height_in_tiles: 64,
|
|
||||||
target_width: 64 * 16,
|
|
||||||
target_height: 64 * 16,
|
|
||||||
layout: Layout {
|
|
||||||
path_tag_base: pathtag_base,
|
|
||||||
path_data_base: pathdata_base,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
let scene_buf = recording.upload("scene", scene);
|
|
||||||
let config_buf = recording.upload_uniform("config", bytemuck::bytes_of(&config));
|
|
||||||
|
|
||||||
let reduced_buf = BufProxy::new(pathtag_wgs as u64 * TAG_MONOID_SIZE, "reduced_buf");
|
|
||||||
// TODO: really only need pathtag_wgs - 1
|
|
||||||
recording.dispatch(
|
|
||||||
shaders.pathtag_reduce,
|
|
||||||
(pathtag_wgs as u32, 1, 1),
|
|
||||||
[config_buf, scene_buf, reduced_buf],
|
|
||||||
);
|
|
||||||
|
|
||||||
let tagmonoid_buf = BufProxy::new(
|
|
||||||
pathtag_wgs as u64 * shaders::PATHTAG_REDUCE_WG as u64 * TAG_MONOID_SIZE,
|
|
||||||
"tagmonoid_buf",
|
|
||||||
);
|
|
||||||
recording.dispatch(
|
|
||||||
shaders.pathtag_scan,
|
|
||||||
(pathtag_wgs as u32, 1, 1),
|
|
||||||
[config_buf, scene_buf, reduced_buf, tagmonoid_buf],
|
|
||||||
);
|
|
||||||
|
|
||||||
let path_coarse_wgs =
|
|
||||||
(n_pathtag as u32 + shaders::PATH_COARSE_WG - 1) / shaders::PATH_COARSE_WG;
|
|
||||||
// TODO: more principled size calc
|
|
||||||
let tiles_buf = BufProxy::new(4097 * 8, "tiles_buf");
|
|
||||||
let segments_buf = BufProxy::new(256 * 24, "segments_buf");
|
|
||||||
recording.clear_all(tiles_buf);
|
|
||||||
recording.dispatch(
|
|
||||||
shaders.path_coarse,
|
|
||||||
(path_coarse_wgs, 1, 1),
|
|
||||||
[
|
|
||||||
config_buf,
|
|
||||||
scene_buf,
|
|
||||||
tagmonoid_buf,
|
|
||||||
tiles_buf,
|
|
||||||
segments_buf,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
recording.dispatch(
|
|
||||||
shaders.backdrop,
|
|
||||||
(config.height_in_tiles, 1, 1),
|
|
||||||
[config_buf, tiles_buf],
|
|
||||||
);
|
|
||||||
let out_buf_size = config.width_in_tiles * config.height_in_tiles * 256;
|
|
||||||
let out_buf = BufProxy::new(out_buf_size as u64, "out_buf");
|
|
||||||
recording.dispatch(
|
|
||||||
shaders.fine,
|
|
||||||
(config.width_in_tiles, config.height_in_tiles, 1),
|
|
||||||
[config_buf, tiles_buf, segments_buf, out_buf],
|
|
||||||
);
|
|
||||||
|
|
||||||
recording.download(out_buf);
|
|
||||||
(recording, out_buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render_full(
|
pub fn render_full(
|
||||||
scene: &Scene,
|
scene: &Scene,
|
||||||
shaders: &FullShaders,
|
shaders: &FullShaders,
|
||||||
|
@ -184,21 +51,11 @@ pub fn render_encoding_full(
|
||||||
(recording, out_image.into())
|
(recording, out_image.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn align_up(len: usize, alignment: u32) -> usize {
|
|
||||||
len + (len.wrapping_neg() & (alignment as usize - 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Render {
|
impl Render {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
// These sizes are adequate for paris-30k but should probably be dialed down.
|
|
||||||
Render {
|
Render {
|
||||||
binning_info_size: (1 << 20) / 4,
|
fine_wg_count: None,
|
||||||
tiles_size: (1 << 24) / TILE_SIZE as u32,
|
fine_resources: None,
|
||||||
segments_size: (1 << 26) / SEGMENT_SIZE as u32,
|
|
||||||
ptcl_size: (1 << 25) / 4 as u32,
|
|
||||||
width_in_tiles: 0,
|
|
||||||
height_in_tiles: 0,
|
|
||||||
fine: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +70,8 @@ impl Render {
|
||||||
params: &RenderParams,
|
params: &RenderParams,
|
||||||
robust: bool,
|
robust: bool,
|
||||||
) -> Recording {
|
) -> Recording {
|
||||||
use crate::encoding::Resolver;
|
use vello_encoding::{RenderConfig, Resolver};
|
||||||
|
|
||||||
let mut recording = Recording::default();
|
let mut recording = Recording::default();
|
||||||
let mut resolver = Resolver::new();
|
let mut resolver = Resolver::new();
|
||||||
let mut packed = vec![];
|
let mut packed = vec![];
|
||||||
|
@ -234,29 +92,6 @@ impl Render {
|
||||||
} else {
|
} else {
|
||||||
ImageProxy::new(images.width, images.height, ImageFormat::Rgba8)
|
ImageProxy::new(images.width, images.height, ImageFormat::Rgba8)
|
||||||
};
|
};
|
||||||
// TODO: calculate for real when we do rectangles
|
|
||||||
let n_pathtag = layout.path_tags(&packed).len();
|
|
||||||
let pathtag_padded = align_up(n_pathtag, 4 * shaders::PATHTAG_REDUCE_WG);
|
|
||||||
let n_paths = layout.n_paths;
|
|
||||||
let n_drawobj = layout.n_paths;
|
|
||||||
let n_clip = layout.n_clips;
|
|
||||||
|
|
||||||
let new_width = next_multiple_of(params.width, 16);
|
|
||||||
let new_height = next_multiple_of(params.height, 16);
|
|
||||||
|
|
||||||
let info_size = layout.bin_data_start;
|
|
||||||
let config = crate::encoding::Config {
|
|
||||||
width_in_tiles: new_width / 16,
|
|
||||||
height_in_tiles: new_height / 16,
|
|
||||||
target_width: params.width,
|
|
||||||
target_height: params.height,
|
|
||||||
base_color: params.base_color.to_premul_u32(),
|
|
||||||
binning_size: self.binning_info_size - info_size,
|
|
||||||
tiles_size: self.tiles_size,
|
|
||||||
segments_size: self.segments_size,
|
|
||||||
ptcl_size: self.ptcl_size,
|
|
||||||
layout: layout,
|
|
||||||
};
|
|
||||||
for image in images.images {
|
for image in images.images {
|
||||||
recording.write_image(
|
recording.write_image(
|
||||||
image_atlas,
|
image_atlas,
|
||||||
|
@ -267,52 +102,54 @@ impl Render {
|
||||||
image.0.data.data(),
|
image.0.data.data(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// println!("{:?}", config);
|
|
||||||
|
let cpu_config =
|
||||||
|
RenderConfig::new(&layout, params.width, params.height, ¶ms.base_color);
|
||||||
|
let buffer_sizes = &cpu_config.buffer_sizes;
|
||||||
|
let wg_counts = &cpu_config.workgroup_counts;
|
||||||
|
|
||||||
let scene_buf = ResourceProxy::Buf(recording.upload("scene", packed));
|
let scene_buf = ResourceProxy::Buf(recording.upload("scene", packed));
|
||||||
let config_buf =
|
let config_buf = ResourceProxy::Buf(
|
||||||
ResourceProxy::Buf(recording.upload_uniform("config", bytemuck::bytes_of(&config)));
|
recording.upload_uniform("config", bytemuck::bytes_of(&cpu_config.gpu)),
|
||||||
|
);
|
||||||
let info_bin_data_buf = ResourceProxy::new_buf(
|
let info_bin_data_buf = ResourceProxy::new_buf(
|
||||||
(info_size + config.binning_size) as u64 * 4,
|
buffer_sizes.bin_data.size_in_bytes() as u64,
|
||||||
"info_bin_data_buf",
|
"info_bin_data_buf",
|
||||||
);
|
);
|
||||||
let tile_buf = ResourceProxy::new_buf(config.tiles_size as u64 * TILE_SIZE, "tile_buf");
|
let tile_buf =
|
||||||
|
ResourceProxy::new_buf(buffer_sizes.tiles.size_in_bytes().into(), "tile_buf");
|
||||||
let segments_buf =
|
let segments_buf =
|
||||||
ResourceProxy::new_buf(config.segments_size as u64 * SEGMENT_SIZE, "segments_buf");
|
ResourceProxy::new_buf(buffer_sizes.segments.size_in_bytes().into(), "segments_buf");
|
||||||
let ptcl_buf = ResourceProxy::new_buf(config.ptcl_size as u64 * 4, "ptcl_buf");
|
let ptcl_buf = ResourceProxy::new_buf(buffer_sizes.ptcl.size_in_bytes().into(), "ptcl_buf");
|
||||||
|
let reduced_buf = ResourceProxy::new_buf(
|
||||||
let pathtag_wgs = pathtag_padded / (4 * shaders::PATHTAG_REDUCE_WG as usize);
|
buffer_sizes.path_reduced.size_in_bytes().into(),
|
||||||
let pathtag_large = pathtag_wgs > shaders::PATHTAG_REDUCE_WG as usize;
|
"reduced_buf",
|
||||||
let reduced_size = if pathtag_large {
|
);
|
||||||
align_up(pathtag_wgs, shaders::PATHTAG_REDUCE_WG)
|
|
||||||
} else {
|
|
||||||
pathtag_wgs
|
|
||||||
};
|
|
||||||
let reduced_buf =
|
|
||||||
ResourceProxy::new_buf(reduced_size as u64 * TAG_MONOID_FULL_SIZE, "reduced_buf");
|
|
||||||
// TODO: really only need pathtag_wgs - 1
|
// TODO: really only need pathtag_wgs - 1
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
shaders.pathtag_reduce,
|
shaders.pathtag_reduce,
|
||||||
(pathtag_wgs as u32, 1, 1),
|
wg_counts.path_reduce,
|
||||||
[config_buf, scene_buf, reduced_buf],
|
[config_buf, scene_buf, reduced_buf],
|
||||||
);
|
);
|
||||||
let mut pathtag_parent = reduced_buf;
|
let mut pathtag_parent = reduced_buf;
|
||||||
let mut large_pathtag_bufs = None;
|
let mut large_pathtag_bufs = None;
|
||||||
if pathtag_large {
|
if wg_counts.use_large_path_scan {
|
||||||
let reduced2_size = shaders::PATHTAG_REDUCE_WG as usize;
|
let reduced2_buf = ResourceProxy::new_buf(
|
||||||
let reduced2_buf =
|
buffer_sizes.path_reduced2.size_in_bytes().into(),
|
||||||
ResourceProxy::new_buf(reduced2_size as u64 * TAG_MONOID_FULL_SIZE, "reduced2_buf");
|
"reduced2_buf",
|
||||||
|
);
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
shaders.pathtag_reduce2,
|
shaders.pathtag_reduce2,
|
||||||
(reduced2_size as u32, 1, 1),
|
wg_counts.path_reduce2,
|
||||||
[reduced_buf, reduced2_buf],
|
[reduced_buf, reduced2_buf],
|
||||||
);
|
);
|
||||||
let reduced_scan_buf = ResourceProxy::new_buf(
|
let reduced_scan_buf = ResourceProxy::new_buf(
|
||||||
pathtag_wgs as u64 * TAG_MONOID_FULL_SIZE,
|
buffer_sizes.path_reduced_scan.size_in_bytes().into(),
|
||||||
"reduced_scan_buf",
|
"reduced_scan_buf",
|
||||||
);
|
);
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
shaders.pathtag_scan1,
|
shaders.pathtag_scan1,
|
||||||
(reduced_size as u32 / shaders::PATHTAG_REDUCE_WG, 1, 1),
|
wg_counts.path_scan1,
|
||||||
[reduced_buf, reduced2_buf, reduced_scan_buf],
|
[reduced_buf, reduced2_buf, reduced_scan_buf],
|
||||||
);
|
);
|
||||||
pathtag_parent = reduced_scan_buf;
|
pathtag_parent = reduced_scan_buf;
|
||||||
|
@ -320,17 +157,17 @@ impl Render {
|
||||||
}
|
}
|
||||||
|
|
||||||
let tagmonoid_buf = ResourceProxy::new_buf(
|
let tagmonoid_buf = ResourceProxy::new_buf(
|
||||||
pathtag_wgs as u64 * shaders::PATHTAG_REDUCE_WG as u64 * TAG_MONOID_FULL_SIZE,
|
buffer_sizes.path_monoids.size_in_bytes().into(),
|
||||||
"tagmonoid_buf",
|
"tagmonoid_buf",
|
||||||
);
|
);
|
||||||
let pathtag_scan = if pathtag_large {
|
let pathtag_scan = if wg_counts.use_large_path_scan {
|
||||||
shaders.pathtag_scan_large
|
shaders.pathtag_scan_large
|
||||||
} else {
|
} else {
|
||||||
shaders.pathtag_scan
|
shaders.pathtag_scan
|
||||||
};
|
};
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
pathtag_scan,
|
pathtag_scan,
|
||||||
(pathtag_wgs as u32, 1, 1),
|
wg_counts.path_scan,
|
||||||
[config_buf, scene_buf, pathtag_parent, tagmonoid_buf],
|
[config_buf, scene_buf, pathtag_parent, tagmonoid_buf],
|
||||||
);
|
);
|
||||||
recording.free_resource(reduced_buf);
|
recording.free_resource(reduced_buf);
|
||||||
|
@ -338,20 +175,20 @@ impl Render {
|
||||||
recording.free_resource(reduced2);
|
recording.free_resource(reduced2);
|
||||||
recording.free_resource(reduced_scan);
|
recording.free_resource(reduced_scan);
|
||||||
}
|
}
|
||||||
let drawobj_wgs = (n_drawobj + shaders::PATH_BBOX_WG - 1) / shaders::PATH_BBOX_WG;
|
let path_bbox_buf = ResourceProxy::new_buf(
|
||||||
let path_bbox_buf =
|
buffer_sizes.path_bboxes.size_in_bytes().into(),
|
||||||
ResourceProxy::new_buf(n_paths as u64 * PATH_BBOX_SIZE, "path_bbox_buf");
|
"path_bbox_buf",
|
||||||
|
);
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
shaders.bbox_clear,
|
shaders.bbox_clear,
|
||||||
(drawobj_wgs, 1, 1),
|
wg_counts.bbox_clear,
|
||||||
[config_buf, path_bbox_buf],
|
[config_buf, path_bbox_buf],
|
||||||
);
|
);
|
||||||
let cubic_buf = ResourceProxy::new_buf(n_pathtag as u64 * CUBIC_SIZE, "cubic_buf");
|
let cubic_buf =
|
||||||
let path_coarse_wgs =
|
ResourceProxy::new_buf(buffer_sizes.cubics.size_in_bytes().into(), "cubic_buf");
|
||||||
(n_pathtag as u32 + shaders::PATH_COARSE_WG - 1) / shaders::PATH_COARSE_WG;
|
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
shaders.pathseg,
|
shaders.pathseg,
|
||||||
(path_coarse_wgs, 1, 1),
|
wg_counts.path_seg,
|
||||||
[
|
[
|
||||||
config_buf,
|
config_buf,
|
||||||
scene_buf,
|
scene_buf,
|
||||||
|
@ -360,19 +197,26 @@ impl Render {
|
||||||
cubic_buf,
|
cubic_buf,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
let draw_reduced_buf =
|
let draw_reduced_buf = ResourceProxy::new_buf(
|
||||||
ResourceProxy::new_buf(drawobj_wgs as u64 * DRAWMONOID_SIZE, "draw_reduced_buf");
|
buffer_sizes.draw_reduced.size_in_bytes().into(),
|
||||||
|
"draw_reduced_buf",
|
||||||
|
);
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
shaders.draw_reduce,
|
shaders.draw_reduce,
|
||||||
(drawobj_wgs, 1, 1),
|
wg_counts.draw_reduce,
|
||||||
[config_buf, scene_buf, draw_reduced_buf],
|
[config_buf, scene_buf, draw_reduced_buf],
|
||||||
);
|
);
|
||||||
let draw_monoid_buf =
|
let draw_monoid_buf = ResourceProxy::new_buf(
|
||||||
ResourceProxy::new_buf(n_drawobj as u64 * DRAWMONOID_SIZE, "draw_monoid_buf");
|
buffer_sizes.draw_monoids.size_in_bytes().into(),
|
||||||
let clip_inp_buf = ResourceProxy::new_buf(n_clip as u64 * CLIP_INP_SIZE, "clip_inp_buf");
|
"draw_monoid_buf",
|
||||||
|
);
|
||||||
|
let clip_inp_buf = ResourceProxy::new_buf(
|
||||||
|
buffer_sizes.clip_inps.size_in_bytes().into(),
|
||||||
|
"clip_inp_buf",
|
||||||
|
);
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
shaders.draw_leaf,
|
shaders.draw_leaf,
|
||||||
(drawobj_wgs, 1, 1),
|
wg_counts.draw_leaf,
|
||||||
[
|
[
|
||||||
config_buf,
|
config_buf,
|
||||||
scene_buf,
|
scene_buf,
|
||||||
|
@ -384,16 +228,16 @@ impl Render {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
recording.free_resource(draw_reduced_buf);
|
recording.free_resource(draw_reduced_buf);
|
||||||
let clip_el_buf = ResourceProxy::new_buf(n_clip as u64 * CLIP_EL_SIZE, "clip_el_buf");
|
let clip_el_buf =
|
||||||
|
ResourceProxy::new_buf(buffer_sizes.clip_els.size_in_bytes().into(), "clip_el_buf");
|
||||||
let clip_bic_buf = ResourceProxy::new_buf(
|
let clip_bic_buf = ResourceProxy::new_buf(
|
||||||
(n_clip / shaders::CLIP_REDUCE_WG) as u64 * CLIP_BIC_SIZE,
|
buffer_sizes.clip_bics.size_in_bytes().into(),
|
||||||
"clip_bic_buf",
|
"clip_bic_buf",
|
||||||
);
|
);
|
||||||
let clip_wg_reduce = n_clip.saturating_sub(1) / shaders::CLIP_REDUCE_WG;
|
if wg_counts.clip_reduce.0 > 0 {
|
||||||
if clip_wg_reduce > 0 {
|
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
shaders.clip_reduce,
|
shaders.clip_reduce,
|
||||||
(clip_wg_reduce, 1, 1),
|
wg_counts.clip_reduce,
|
||||||
[
|
[
|
||||||
config_buf,
|
config_buf,
|
||||||
clip_inp_buf,
|
clip_inp_buf,
|
||||||
|
@ -403,12 +247,14 @@ impl Render {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let clip_wg = (n_clip + shaders::CLIP_REDUCE_WG - 1) / shaders::CLIP_REDUCE_WG;
|
let clip_bbox_buf = ResourceProxy::new_buf(
|
||||||
let clip_bbox_buf = ResourceProxy::new_buf(n_clip as u64 * CLIP_BBOX_SIZE, "clip_bbox_buf");
|
buffer_sizes.clip_bboxes.size_in_bytes().into(),
|
||||||
if clip_wg > 0 {
|
"clip_bbox_buf",
|
||||||
|
);
|
||||||
|
if wg_counts.clip_leaf.0 > 0 {
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
shaders.clip_leaf,
|
shaders.clip_leaf,
|
||||||
(clip_wg, 1, 1),
|
wg_counts.clip_leaf,
|
||||||
[
|
[
|
||||||
config_buf,
|
config_buf,
|
||||||
clip_inp_buf,
|
clip_inp_buf,
|
||||||
|
@ -423,20 +269,20 @@ impl Render {
|
||||||
recording.free_resource(clip_inp_buf);
|
recording.free_resource(clip_inp_buf);
|
||||||
recording.free_resource(clip_bic_buf);
|
recording.free_resource(clip_bic_buf);
|
||||||
recording.free_resource(clip_el_buf);
|
recording.free_resource(clip_el_buf);
|
||||||
let draw_bbox_buf =
|
let draw_bbox_buf = ResourceProxy::new_buf(
|
||||||
ResourceProxy::new_buf(n_paths as u64 * DRAW_BBOX_SIZE, "draw_bbox_buf");
|
buffer_sizes.draw_bboxes.size_in_bytes().into(),
|
||||||
let bump_buf = BufProxy::new(BUMP_SIZE, "bump_buf");
|
"draw_bbox_buf",
|
||||||
let width_in_bins = (config.width_in_tiles + 15) / 16;
|
);
|
||||||
let height_in_bins = (config.height_in_tiles + 15) / 16;
|
let bump_buf = BufProxy::new(buffer_sizes.bump_alloc.size_in_bytes().into(), "bump_buf");
|
||||||
let bin_header_buf = ResourceProxy::new_buf(
|
let bin_header_buf = ResourceProxy::new_buf(
|
||||||
(256 * drawobj_wgs) as u64 * BIN_HEADER_SIZE,
|
buffer_sizes.bin_headers.size_in_bytes().into(),
|
||||||
"bin_header_buf",
|
"bin_header_buf",
|
||||||
);
|
);
|
||||||
recording.clear_all(bump_buf);
|
recording.clear_all(bump_buf);
|
||||||
let bump_buf = ResourceProxy::Buf(bump_buf);
|
let bump_buf = ResourceProxy::Buf(bump_buf);
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
shaders.binning,
|
shaders.binning,
|
||||||
(drawobj_wgs, 1, 1),
|
wg_counts.binning,
|
||||||
[
|
[
|
||||||
config_buf,
|
config_buf,
|
||||||
draw_monoid_buf,
|
draw_monoid_buf,
|
||||||
|
@ -453,12 +299,11 @@ impl Render {
|
||||||
recording.free_resource(clip_bbox_buf);
|
recording.free_resource(clip_bbox_buf);
|
||||||
// Note: this only needs to be rounded up because of the workaround to store the tile_offset
|
// Note: this only needs to be rounded up because of the workaround to store the tile_offset
|
||||||
// in storage rather than workgroup memory.
|
// in storage rather than workgroup memory.
|
||||||
let n_path_aligned = align_up(n_paths as usize, 256);
|
let path_buf =
|
||||||
let path_buf = ResourceProxy::new_buf(n_path_aligned as u64 * PATH_SIZE, "path_buf");
|
ResourceProxy::new_buf(buffer_sizes.paths.size_in_bytes().into(), "path_buf");
|
||||||
let path_wgs = (n_paths + shaders::PATH_BBOX_WG - 1) / shaders::PATH_BBOX_WG;
|
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
shaders.tile_alloc,
|
shaders.tile_alloc,
|
||||||
(path_wgs, 1, 1),
|
wg_counts.tile_alloc,
|
||||||
[
|
[
|
||||||
config_buf,
|
config_buf,
|
||||||
scene_buf,
|
scene_buf,
|
||||||
|
@ -471,7 +316,7 @@ impl Render {
|
||||||
recording.free_resource(draw_bbox_buf);
|
recording.free_resource(draw_bbox_buf);
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
shaders.path_coarse,
|
shaders.path_coarse,
|
||||||
(path_coarse_wgs, 1, 1),
|
wg_counts.path_coarse,
|
||||||
[
|
[
|
||||||
config_buf,
|
config_buf,
|
||||||
scene_buf,
|
scene_buf,
|
||||||
|
@ -487,12 +332,12 @@ impl Render {
|
||||||
recording.free_resource(cubic_buf);
|
recording.free_resource(cubic_buf);
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
shaders.backdrop,
|
shaders.backdrop,
|
||||||
(path_wgs, 1, 1),
|
wg_counts.backdrop,
|
||||||
[config_buf, path_buf, tile_buf],
|
[config_buf, path_buf, tile_buf],
|
||||||
);
|
);
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
shaders.coarse,
|
shaders.coarse,
|
||||||
(width_in_bins, height_in_bins, 1),
|
wg_counts.coarse,
|
||||||
[
|
[
|
||||||
config_buf,
|
config_buf,
|
||||||
scene_buf,
|
scene_buf,
|
||||||
|
@ -510,9 +355,8 @@ impl Render {
|
||||||
recording.free_resource(bin_header_buf);
|
recording.free_resource(bin_header_buf);
|
||||||
recording.free_resource(path_buf);
|
recording.free_resource(path_buf);
|
||||||
let out_image = ImageProxy::new(params.width, params.height, ImageFormat::Rgba8);
|
let out_image = ImageProxy::new(params.width, params.height, ImageFormat::Rgba8);
|
||||||
self.width_in_tiles = config.width_in_tiles;
|
self.fine_wg_count = Some(wg_counts.fine);
|
||||||
self.height_in_tiles = config.height_in_tiles;
|
self.fine_resources = Some(FineResources {
|
||||||
self.fine = Some(FineResources {
|
|
||||||
config_buf,
|
config_buf,
|
||||||
bump_buf,
|
bump_buf,
|
||||||
tile_buf,
|
tile_buf,
|
||||||
|
@ -532,10 +376,11 @@ impl Render {
|
||||||
|
|
||||||
/// Run fine rasterization assuming the coarse phase succeeded.
|
/// Run fine rasterization assuming the coarse phase succeeded.
|
||||||
pub fn record_fine(&mut self, shaders: &FullShaders, recording: &mut Recording) {
|
pub fn record_fine(&mut self, shaders: &FullShaders, recording: &mut Recording) {
|
||||||
let fine = self.fine.take().unwrap();
|
let fine_wg_count = self.fine_wg_count.take().unwrap();
|
||||||
|
let fine = self.fine_resources.take().unwrap();
|
||||||
recording.dispatch(
|
recording.dispatch(
|
||||||
shaders.fine,
|
shaders.fine,
|
||||||
(self.width_in_tiles, self.height_in_tiles, 1),
|
fine_wg_count,
|
||||||
[
|
[
|
||||||
fine.config_buf,
|
fine.config_buf,
|
||||||
fine.tile_buf,
|
fine.tile_buf,
|
||||||
|
@ -561,10 +406,16 @@ impl Render {
|
||||||
/// This is going away, as the caller will add the output image to the bind
|
/// This is going away, as the caller will add the output image to the bind
|
||||||
/// map.
|
/// map.
|
||||||
pub fn out_image(&self) -> ImageProxy {
|
pub fn out_image(&self) -> ImageProxy {
|
||||||
self.fine.as_ref().unwrap().out_image
|
self.fine_resources.as_ref().unwrap().out_image
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bump_buf(&self) -> BufProxy {
|
pub fn bump_buf(&self) -> BufProxy {
|
||||||
*self.fine.as_ref().unwrap().bump_buf.as_buf().unwrap()
|
*self
|
||||||
|
.fine_resources
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.bump_buf
|
||||||
|
.as_buf()
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,7 @@
|
||||||
use fello::NormalizedCoord;
|
use fello::NormalizedCoord;
|
||||||
use peniko::kurbo::{Affine, Rect, Shape};
|
use peniko::kurbo::{Affine, Rect, Shape};
|
||||||
use peniko::{BlendMode, BrushRef, Color, Fill, Font, Image, Stroke, StyleRef};
|
use peniko::{BlendMode, BrushRef, Color, Fill, Font, Image, Stroke, StyleRef};
|
||||||
|
use vello_encoding::{Encoding, Glyph, GlyphRun, Patch, Transform};
|
||||||
use crate::encoding::{Encoding, Glyph, GlyphRun, Patch, Transform};
|
|
||||||
|
|
||||||
/// Encoded definition of a scene and associated resources.
|
/// Encoded definition of a scene and associated resources.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
|
@ -24,12 +24,6 @@ use wgpu::Device;
|
||||||
|
|
||||||
use crate::engine::{BindType, Engine, Error, ImageFormat, ShaderId};
|
use crate::engine::{BindType, Engine, Error, ImageFormat, ShaderId};
|
||||||
|
|
||||||
pub const PATHTAG_REDUCE_WG: u32 = 256;
|
|
||||||
pub const PATH_BBOX_WG: u32 = 256;
|
|
||||||
pub const PATH_COARSE_WG: u32 = 256;
|
|
||||||
pub const PATH_DRAWOBJ_WG: u32 = 256;
|
|
||||||
pub const CLIP_REDUCE_WG: u32 = 256;
|
|
||||||
|
|
||||||
macro_rules! shader {
|
macro_rules! shader {
|
||||||
($name:expr) => {&{
|
($name:expr) => {&{
|
||||||
let shader = include_str!(concat!(
|
let shader = include_str!(concat!(
|
||||||
|
@ -56,14 +50,6 @@ macro_rules! shader {
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Shaders {
|
|
||||||
pub pathtag_reduce: ShaderId,
|
|
||||||
pub pathtag_scan: ShaderId,
|
|
||||||
pub path_coarse: ShaderId,
|
|
||||||
pub backdrop: ShaderId,
|
|
||||||
pub fine: ShaderId,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shaders for the full pipeline
|
// Shaders for the full pipeline
|
||||||
pub struct FullShaders {
|
pub struct FullShaders {
|
||||||
pub pathtag_reduce: ShaderId,
|
pub pathtag_reduce: ShaderId,
|
||||||
|
@ -85,70 +71,6 @@ pub struct FullShaders {
|
||||||
pub fine: ShaderId,
|
pub fine: ShaderId,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_shaders(device: &Device, engine: &mut Engine) -> Result<Shaders, Error> {
|
|
||||||
let imports = SHARED_SHADERS
|
|
||||||
.iter()
|
|
||||||
.copied()
|
|
||||||
.collect::<std::collections::HashMap<_, _>>();
|
|
||||||
let empty = HashSet::new();
|
|
||||||
let pathtag_reduce = engine.add_shader(
|
|
||||||
device,
|
|
||||||
"pathtag_reduce",
|
|
||||||
preprocess::preprocess(shader!("pathtag_reduce"), &empty, &imports).into(),
|
|
||||||
&[BindType::Uniform, BindType::BufReadOnly, BindType::Buffer],
|
|
||||||
)?;
|
|
||||||
let pathtag_scan = engine.add_shader(
|
|
||||||
device,
|
|
||||||
"pathtag_scan",
|
|
||||||
preprocess::preprocess(shader!("pathtag_scan"), &empty, &imports).into(),
|
|
||||||
&[
|
|
||||||
BindType::Uniform,
|
|
||||||
BindType::BufReadOnly,
|
|
||||||
BindType::BufReadOnly,
|
|
||||||
BindType::Buffer,
|
|
||||||
],
|
|
||||||
)?;
|
|
||||||
let path_coarse_config = HashSet::new();
|
|
||||||
// path_coarse_config.add("cubics_out");
|
|
||||||
|
|
||||||
let path_coarse = engine.add_shader(
|
|
||||||
device,
|
|
||||||
"path_coarse",
|
|
||||||
preprocess::preprocess(shader!("path_coarse"), &path_coarse_config, &imports).into(),
|
|
||||||
&[
|
|
||||||
BindType::Uniform,
|
|
||||||
BindType::BufReadOnly,
|
|
||||||
BindType::BufReadOnly,
|
|
||||||
BindType::Buffer,
|
|
||||||
BindType::Buffer,
|
|
||||||
],
|
|
||||||
)?;
|
|
||||||
let backdrop = engine.add_shader(
|
|
||||||
device,
|
|
||||||
"backdrop",
|
|
||||||
preprocess::preprocess(shader!("backdrop"), &empty, &imports).into(),
|
|
||||||
&[BindType::Uniform, BindType::Buffer],
|
|
||||||
)?;
|
|
||||||
let fine = engine.add_shader(
|
|
||||||
device,
|
|
||||||
"fine",
|
|
||||||
preprocess::preprocess(shader!("fine"), &empty, &imports).into(),
|
|
||||||
&[
|
|
||||||
BindType::Uniform,
|
|
||||||
BindType::BufReadOnly,
|
|
||||||
BindType::BufReadOnly,
|
|
||||||
BindType::Buffer,
|
|
||||||
],
|
|
||||||
)?;
|
|
||||||
Ok(Shaders {
|
|
||||||
pathtag_reduce,
|
|
||||||
pathtag_scan,
|
|
||||||
path_coarse,
|
|
||||||
backdrop,
|
|
||||||
fine,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn full_shaders(device: &Device, engine: &mut Engine) -> Result<FullShaders, Error> {
|
pub fn full_shaders(device: &Device, engine: &mut Engine) -> Result<FullShaders, Error> {
|
||||||
let imports = SHARED_SHADERS
|
let imports = SHARED_SHADERS
|
||||||
.iter()
|
.iter()
|
||||||
|
|
Loading…
Reference in a new issue