mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-09 20:31:29 +11:00
Create Render struct
Separate coarse and fine stages as separate methods of Render struct.
This commit is contained in:
parent
e47c5777cc
commit
17907893af
695
src/render.rs
695
src/render.rs
|
@ -9,6 +9,34 @@ use crate::{
|
|||
Scene,
|
||||
};
|
||||
|
||||
/// State for a render in progress.
|
||||
pub struct Render {
|
||||
/// Size of binning and info combined buffer in u32 units
|
||||
binning_info_size: u32,
|
||||
/// 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.
|
||||
struct FineResources {
|
||||
config_buf: ResourceProxy,
|
||||
bump_buf: ResourceProxy,
|
||||
tile_buf: ResourceProxy,
|
||||
segments_buf: ResourceProxy,
|
||||
ptcl_buf: ResourceProxy,
|
||||
gradient_image: ResourceProxy,
|
||||
info_bin_data_buf: ResourceProxy,
|
||||
|
||||
out_image: ImageProxy,
|
||||
}
|
||||
|
||||
const TAG_MONOID_SIZE: u64 = 12;
|
||||
const TAG_MONOID_FULL_SIZE: u64 = 20;
|
||||
const PATH_BBOX_SIZE: u64 = 24;
|
||||
|
@ -157,317 +185,378 @@ pub fn render_full(
|
|||
render_encoding_full(scene.data(), shaders, width, height)
|
||||
}
|
||||
|
||||
/// Create a single recording with both coarse and fine render stages.
|
||||
///
|
||||
/// This function is not recommended when the scene can be complex, as it does not
|
||||
/// implement robust dynamic memory.
|
||||
pub fn render_encoding_full(
|
||||
encoding: &Encoding,
|
||||
shaders: &FullShaders,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) -> (Recording, ResourceProxy) {
|
||||
use crate::encoding::{resource::ResourceCache, PackedEncoding};
|
||||
let mut recording = Recording::default();
|
||||
let mut resources = ResourceCache::new();
|
||||
let mut packed = PackedEncoding::default();
|
||||
packed.pack(encoding, &mut resources);
|
||||
let (ramp_data, ramps_width, ramps_height) = resources.ramps(packed.resources).unwrap();
|
||||
let gradient_image = if encoding.patches.is_empty() {
|
||||
ResourceProxy::new_image(1, 1, ImageFormat::Rgba8)
|
||||
} else {
|
||||
let data: &[u8] = bytemuck::cast_slice(ramp_data);
|
||||
ResourceProxy::Image(recording.upload_image(
|
||||
ramps_width,
|
||||
ramps_height,
|
||||
ImageFormat::Rgba8,
|
||||
data,
|
||||
))
|
||||
};
|
||||
// TODO: calculate for real when we do rectangles
|
||||
let n_pathtag = encoding.path_tags.len();
|
||||
let pathtag_padded = align_up(encoding.path_tags.len(), 4 * shaders::PATHTAG_REDUCE_WG);
|
||||
let n_paths = encoding.n_paths;
|
||||
let n_drawobj = n_paths;
|
||||
let n_clip = encoding.n_clips;
|
||||
|
||||
let new_width = next_multiple_of(width, 16);
|
||||
let new_height = next_multiple_of(height, 16);
|
||||
|
||||
let info_size = packed.layout.bin_data_start;
|
||||
let config = crate::encoding::Config {
|
||||
width_in_tiles: new_width / 16,
|
||||
height_in_tiles: new_height / 16,
|
||||
target_width: width,
|
||||
target_height: height,
|
||||
binning_size: ((1 << 20) / 4) - info_size,
|
||||
tiles_size: (1 << 24) / TILE_SIZE as u32,
|
||||
segments_size: (1 << 26) / SEGMENT_SIZE as u32,
|
||||
ptcl_size: (1 << 25) / 4,
|
||||
layout: packed.layout,
|
||||
};
|
||||
// println!("{:?}", config);
|
||||
let scene_buf = ResourceProxy::Buf(recording.upload("scene", packed.data));
|
||||
let config_buf =
|
||||
ResourceProxy::Buf(recording.upload_uniform("config", bytemuck::bytes_of(&config)));
|
||||
let info_bin_data_buf = ResourceProxy::new_buf(
|
||||
(info_size + config.binning_size) as u64 * 4,
|
||||
"info_bin_data_buf",
|
||||
);
|
||||
let tile_buf = ResourceProxy::new_buf(config.tiles_size as u64 * TILE_SIZE, "tile_buf");
|
||||
let segments_buf =
|
||||
ResourceProxy::new_buf(config.segments_size as u64 * SEGMENT_SIZE, "segments_buf");
|
||||
let ptcl_buf = ResourceProxy::new_buf(config.ptcl_size as u64 * 4, "ptcl_buf");
|
||||
|
||||
let pathtag_wgs = pathtag_padded / (4 * shaders::PATHTAG_REDUCE_WG as usize);
|
||||
let pathtag_large = pathtag_wgs > shaders::PATHTAG_REDUCE_WG as usize;
|
||||
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
|
||||
recording.dispatch(
|
||||
shaders.pathtag_reduce,
|
||||
(pathtag_wgs as u32, 1, 1),
|
||||
[config_buf, scene_buf, reduced_buf],
|
||||
);
|
||||
let mut pathtag_parent = reduced_buf;
|
||||
let mut large_pathtag_bufs = None;
|
||||
if pathtag_large {
|
||||
let reduced2_size = shaders::PATHTAG_REDUCE_WG as usize;
|
||||
let reduced2_buf =
|
||||
ResourceProxy::new_buf(reduced2_size as u64 * TAG_MONOID_FULL_SIZE, "reduced2_buf");
|
||||
recording.dispatch(
|
||||
shaders.pathtag_reduce2,
|
||||
(reduced2_size as u32, 1, 1),
|
||||
[reduced_buf, reduced2_buf],
|
||||
);
|
||||
let reduced_scan_buf = ResourceProxy::new_buf(
|
||||
pathtag_wgs as u64 * TAG_MONOID_FULL_SIZE,
|
||||
"reduced_scan_buf",
|
||||
);
|
||||
recording.dispatch(
|
||||
shaders.pathtag_scan1,
|
||||
(reduced_size as u32 / shaders::PATHTAG_REDUCE_WG, 1, 1),
|
||||
[reduced_buf, reduced2_buf, reduced_scan_buf],
|
||||
);
|
||||
pathtag_parent = reduced_scan_buf;
|
||||
large_pathtag_bufs = Some((reduced2_buf, reduced_scan_buf));
|
||||
}
|
||||
|
||||
let tagmonoid_buf = ResourceProxy::new_buf(
|
||||
pathtag_wgs as u64 * shaders::PATHTAG_REDUCE_WG as u64 * TAG_MONOID_FULL_SIZE,
|
||||
"tagmonoid_buf",
|
||||
);
|
||||
let pathtag_scan = if pathtag_large {
|
||||
shaders.pathtag_scan_large
|
||||
} else {
|
||||
shaders.pathtag_scan
|
||||
};
|
||||
recording.dispatch(
|
||||
pathtag_scan,
|
||||
(pathtag_wgs as u32, 1, 1),
|
||||
[config_buf, scene_buf, pathtag_parent, tagmonoid_buf],
|
||||
);
|
||||
recording.free_resource(reduced_buf);
|
||||
if let Some((reduced2, reduced_scan)) = large_pathtag_bufs {
|
||||
recording.free_resource(reduced2);
|
||||
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(n_paths as u64 * PATH_BBOX_SIZE, "path_bbox_buf");
|
||||
recording.dispatch(
|
||||
shaders.bbox_clear,
|
||||
(drawobj_wgs, 1, 1),
|
||||
[config_buf, path_bbox_buf],
|
||||
);
|
||||
let cubic_buf = ResourceProxy::new_buf(n_pathtag as u64 * CUBIC_SIZE, "cubic_buf");
|
||||
let path_coarse_wgs =
|
||||
(n_pathtag as u32 + shaders::PATH_COARSE_WG - 1) / shaders::PATH_COARSE_WG;
|
||||
recording.dispatch(
|
||||
shaders.pathseg,
|
||||
(path_coarse_wgs, 1, 1),
|
||||
[
|
||||
config_buf,
|
||||
scene_buf,
|
||||
tagmonoid_buf,
|
||||
path_bbox_buf,
|
||||
cubic_buf,
|
||||
],
|
||||
);
|
||||
let draw_reduced_buf =
|
||||
ResourceProxy::new_buf(drawobj_wgs as u64 * DRAWMONOID_SIZE, "draw_reduced_buf");
|
||||
recording.dispatch(
|
||||
shaders.draw_reduce,
|
||||
(drawobj_wgs, 1, 1),
|
||||
[config_buf, scene_buf, draw_reduced_buf],
|
||||
);
|
||||
let draw_monoid_buf =
|
||||
ResourceProxy::new_buf(n_drawobj as u64 * DRAWMONOID_SIZE, "draw_monoid_buf");
|
||||
let clip_inp_buf =
|
||||
ResourceProxy::new_buf(encoding.n_clips as u64 * CLIP_INP_SIZE, "clip_inp_buf");
|
||||
recording.dispatch(
|
||||
shaders.draw_leaf,
|
||||
(drawobj_wgs, 1, 1),
|
||||
[
|
||||
config_buf,
|
||||
scene_buf,
|
||||
draw_reduced_buf,
|
||||
path_bbox_buf,
|
||||
draw_monoid_buf,
|
||||
info_bin_data_buf,
|
||||
clip_inp_buf,
|
||||
],
|
||||
);
|
||||
recording.free_resource(draw_reduced_buf);
|
||||
let clip_el_buf = ResourceProxy::new_buf(encoding.n_clips as u64 * CLIP_EL_SIZE, "clip_el_buf");
|
||||
let clip_bic_buf = ResourceProxy::new_buf(
|
||||
(n_clip / shaders::CLIP_REDUCE_WG) as u64 * CLIP_BIC_SIZE,
|
||||
"clip_bic_buf",
|
||||
);
|
||||
let clip_wg_reduce = n_clip.saturating_sub(1) / shaders::CLIP_REDUCE_WG;
|
||||
if clip_wg_reduce > 0 {
|
||||
recording.dispatch(
|
||||
shaders.clip_reduce,
|
||||
(clip_wg_reduce, 1, 1),
|
||||
[
|
||||
config_buf,
|
||||
clip_inp_buf,
|
||||
path_bbox_buf,
|
||||
clip_bic_buf,
|
||||
clip_el_buf,
|
||||
],
|
||||
);
|
||||
}
|
||||
let clip_wg = (n_clip + shaders::CLIP_REDUCE_WG - 1) / shaders::CLIP_REDUCE_WG;
|
||||
let clip_bbox_buf = ResourceProxy::new_buf(n_clip as u64 * CLIP_BBOX_SIZE, "clip_bbox_buf");
|
||||
if clip_wg > 0 {
|
||||
recording.dispatch(
|
||||
shaders.clip_leaf,
|
||||
(clip_wg, 1, 1),
|
||||
[
|
||||
config_buf,
|
||||
clip_inp_buf,
|
||||
path_bbox_buf,
|
||||
clip_bic_buf,
|
||||
clip_el_buf,
|
||||
draw_monoid_buf,
|
||||
clip_bbox_buf,
|
||||
],
|
||||
);
|
||||
}
|
||||
recording.free_resource(clip_inp_buf);
|
||||
recording.free_resource(clip_bic_buf);
|
||||
recording.free_resource(clip_el_buf);
|
||||
let draw_bbox_buf = ResourceProxy::new_buf(n_paths as u64 * DRAW_BBOX_SIZE, "draw_bbox_buf");
|
||||
let bump_buf = BufProxy::new(BUMP_SIZE, "bump_buf");
|
||||
let width_in_bins = (config.width_in_tiles + 15) / 16;
|
||||
let height_in_bins = (config.height_in_tiles + 15) / 16;
|
||||
let bin_header_buf = ResourceProxy::new_buf(
|
||||
(256 * drawobj_wgs) as u64 * BIN_HEADER_SIZE,
|
||||
"bin_header_buf",
|
||||
);
|
||||
recording.clear_all(bump_buf);
|
||||
let bump_buf = ResourceProxy::Buf(bump_buf);
|
||||
recording.dispatch(
|
||||
shaders.binning,
|
||||
(drawobj_wgs, 1, 1),
|
||||
[
|
||||
config_buf,
|
||||
draw_monoid_buf,
|
||||
path_bbox_buf,
|
||||
clip_bbox_buf,
|
||||
draw_bbox_buf,
|
||||
bump_buf,
|
||||
info_bin_data_buf,
|
||||
bin_header_buf,
|
||||
],
|
||||
);
|
||||
recording.free_resource(draw_monoid_buf);
|
||||
recording.free_resource(path_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
|
||||
// in storage rather than workgroup memory.
|
||||
let n_path_aligned = align_up(n_paths as usize, 256);
|
||||
let path_buf = ResourceProxy::new_buf(n_path_aligned as u64 * PATH_SIZE, "path_buf");
|
||||
let path_wgs = (n_paths + shaders::PATH_BBOX_WG - 1) / shaders::PATH_BBOX_WG;
|
||||
recording.dispatch(
|
||||
shaders.tile_alloc,
|
||||
(path_wgs, 1, 1),
|
||||
[
|
||||
config_buf,
|
||||
scene_buf,
|
||||
draw_bbox_buf,
|
||||
bump_buf,
|
||||
path_buf,
|
||||
tile_buf,
|
||||
],
|
||||
);
|
||||
recording.free_resource(draw_bbox_buf);
|
||||
recording.dispatch(
|
||||
shaders.path_coarse,
|
||||
(path_coarse_wgs, 1, 1),
|
||||
[
|
||||
config_buf,
|
||||
scene_buf,
|
||||
tagmonoid_buf,
|
||||
cubic_buf,
|
||||
path_buf,
|
||||
bump_buf,
|
||||
tile_buf,
|
||||
segments_buf,
|
||||
],
|
||||
);
|
||||
recording.free_resource(tagmonoid_buf);
|
||||
recording.free_resource(cubic_buf);
|
||||
recording.dispatch(
|
||||
shaders.backdrop,
|
||||
(path_wgs, 1, 1),
|
||||
[config_buf, path_buf, tile_buf],
|
||||
);
|
||||
recording.dispatch(
|
||||
shaders.coarse,
|
||||
(width_in_bins, height_in_bins, 1),
|
||||
[
|
||||
config_buf,
|
||||
scene_buf,
|
||||
draw_monoid_buf,
|
||||
bin_header_buf,
|
||||
info_bin_data_buf,
|
||||
path_buf,
|
||||
tile_buf,
|
||||
bump_buf,
|
||||
ptcl_buf,
|
||||
],
|
||||
);
|
||||
recording.free_resource(scene_buf);
|
||||
recording.free_resource(draw_monoid_buf);
|
||||
recording.free_resource(bin_header_buf);
|
||||
recording.free_resource(path_buf);
|
||||
// TODO: bump_buf is special
|
||||
recording.free_resource(bump_buf);
|
||||
let out_image = ImageProxy::new(width, height, ImageFormat::Rgba8);
|
||||
recording.dispatch(
|
||||
shaders.fine,
|
||||
(config.width_in_tiles, config.height_in_tiles, 1),
|
||||
[
|
||||
config_buf,
|
||||
tile_buf,
|
||||
segments_buf,
|
||||
ResourceProxy::Image(out_image),
|
||||
ptcl_buf,
|
||||
gradient_image,
|
||||
info_bin_data_buf,
|
||||
],
|
||||
);
|
||||
recording.free_resource(config_buf);
|
||||
recording.free_resource(tile_buf);
|
||||
recording.free_resource(segments_buf);
|
||||
recording.free_resource(ptcl_buf);
|
||||
recording.free_resource(gradient_image);
|
||||
recording.free_resource(info_bin_data_buf);
|
||||
(recording, ResourceProxy::Image(out_image))
|
||||
let mut render = Render::new();
|
||||
let mut recording = render.render_encoding_coarse(encoding, shaders, width, height);
|
||||
let out_image = render.out_image();
|
||||
render.record_fine(shaders, &mut recording);
|
||||
(recording, out_image.into())
|
||||
}
|
||||
|
||||
pub fn align_up(len: usize, alignment: u32) -> usize {
|
||||
len + (len.wrapping_neg() & (alignment as usize - 1))
|
||||
}
|
||||
|
||||
impl Render {
|
||||
pub fn new() -> Self {
|
||||
// These sizes are adequate for paris-30k but should probably be dialed down.
|
||||
Render {
|
||||
binning_info_size: (1 << 20) / 4,
|
||||
tiles_size: (1 << 24) / TILE_SIZE as u32,
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepare a recording for the coarse rasterization phase.
|
||||
pub fn render_encoding_coarse(
|
||||
&mut self,
|
||||
encoding: &Encoding,
|
||||
shaders: &FullShaders,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) -> Recording {
|
||||
use crate::encoding::{resource::ResourceCache, PackedEncoding};
|
||||
let mut recording = Recording::default();
|
||||
let mut resources = ResourceCache::new();
|
||||
let mut packed = PackedEncoding::default();
|
||||
packed.pack(encoding, &mut resources);
|
||||
let (ramp_data, ramps_width, ramps_height) = resources.ramps(packed.resources).unwrap();
|
||||
let gradient_image = if encoding.patches.is_empty() {
|
||||
ResourceProxy::new_image(1, 1, ImageFormat::Rgba8)
|
||||
} else {
|
||||
let data: &[u8] = bytemuck::cast_slice(ramp_data);
|
||||
ResourceProxy::Image(recording.upload_image(
|
||||
ramps_width,
|
||||
ramps_height,
|
||||
ImageFormat::Rgba8,
|
||||
data,
|
||||
))
|
||||
};
|
||||
// TODO: calculate for real when we do rectangles
|
||||
let n_pathtag = encoding.path_tags.len();
|
||||
let pathtag_padded = align_up(encoding.path_tags.len(), 4 * shaders::PATHTAG_REDUCE_WG);
|
||||
let n_paths = encoding.n_paths;
|
||||
let n_drawobj = n_paths;
|
||||
let n_clip = encoding.n_clips;
|
||||
|
||||
let new_width = next_multiple_of(width, 16);
|
||||
let new_height = next_multiple_of(height, 16);
|
||||
|
||||
let info_size = packed.layout.bin_data_start;
|
||||
let config = crate::encoding::Config {
|
||||
width_in_tiles: new_width / 16,
|
||||
height_in_tiles: new_height / 16,
|
||||
target_width: width,
|
||||
target_height: height,
|
||||
binning_size: self.binning_info_size - info_size,
|
||||
tiles_size: self.tiles_size,
|
||||
segments_size: self.segments_size,
|
||||
ptcl_size: self.ptcl_size,
|
||||
layout: packed.layout,
|
||||
};
|
||||
// println!("{:?}", config);
|
||||
let scene_buf = ResourceProxy::Buf(recording.upload("scene", packed.data));
|
||||
let config_buf =
|
||||
ResourceProxy::Buf(recording.upload_uniform("config", bytemuck::bytes_of(&config)));
|
||||
let info_bin_data_buf = ResourceProxy::new_buf(
|
||||
(info_size + config.binning_size) as u64 * 4,
|
||||
"info_bin_data_buf",
|
||||
);
|
||||
let tile_buf = ResourceProxy::new_buf(config.tiles_size as u64 * TILE_SIZE, "tile_buf");
|
||||
let segments_buf =
|
||||
ResourceProxy::new_buf(config.segments_size as u64 * SEGMENT_SIZE, "segments_buf");
|
||||
let ptcl_buf = ResourceProxy::new_buf(config.ptcl_size as u64 * 4, "ptcl_buf");
|
||||
|
||||
let pathtag_wgs = pathtag_padded / (4 * shaders::PATHTAG_REDUCE_WG as usize);
|
||||
let pathtag_large = pathtag_wgs > shaders::PATHTAG_REDUCE_WG as usize;
|
||||
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
|
||||
recording.dispatch(
|
||||
shaders.pathtag_reduce,
|
||||
(pathtag_wgs as u32, 1, 1),
|
||||
[config_buf, scene_buf, reduced_buf],
|
||||
);
|
||||
let mut pathtag_parent = reduced_buf;
|
||||
let mut large_pathtag_bufs = None;
|
||||
if pathtag_large {
|
||||
let reduced2_size = shaders::PATHTAG_REDUCE_WG as usize;
|
||||
let reduced2_buf =
|
||||
ResourceProxy::new_buf(reduced2_size as u64 * TAG_MONOID_FULL_SIZE, "reduced2_buf");
|
||||
recording.dispatch(
|
||||
shaders.pathtag_reduce2,
|
||||
(reduced2_size as u32, 1, 1),
|
||||
[reduced_buf, reduced2_buf],
|
||||
);
|
||||
let reduced_scan_buf = ResourceProxy::new_buf(
|
||||
pathtag_wgs as u64 * TAG_MONOID_FULL_SIZE,
|
||||
"reduced_scan_buf",
|
||||
);
|
||||
recording.dispatch(
|
||||
shaders.pathtag_scan1,
|
||||
(reduced_size as u32 / shaders::PATHTAG_REDUCE_WG, 1, 1),
|
||||
[reduced_buf, reduced2_buf, reduced_scan_buf],
|
||||
);
|
||||
pathtag_parent = reduced_scan_buf;
|
||||
large_pathtag_bufs = Some((reduced2_buf, reduced_scan_buf));
|
||||
}
|
||||
|
||||
let tagmonoid_buf = ResourceProxy::new_buf(
|
||||
pathtag_wgs as u64 * shaders::PATHTAG_REDUCE_WG as u64 * TAG_MONOID_FULL_SIZE,
|
||||
"tagmonoid_buf",
|
||||
);
|
||||
let pathtag_scan = if pathtag_large {
|
||||
shaders.pathtag_scan_large
|
||||
} else {
|
||||
shaders.pathtag_scan
|
||||
};
|
||||
recording.dispatch(
|
||||
pathtag_scan,
|
||||
(pathtag_wgs as u32, 1, 1),
|
||||
[config_buf, scene_buf, pathtag_parent, tagmonoid_buf],
|
||||
);
|
||||
recording.free_resource(reduced_buf);
|
||||
if let Some((reduced2, reduced_scan)) = large_pathtag_bufs {
|
||||
recording.free_resource(reduced2);
|
||||
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(n_paths as u64 * PATH_BBOX_SIZE, "path_bbox_buf");
|
||||
recording.dispatch(
|
||||
shaders.bbox_clear,
|
||||
(drawobj_wgs, 1, 1),
|
||||
[config_buf, path_bbox_buf],
|
||||
);
|
||||
let cubic_buf = ResourceProxy::new_buf(n_pathtag as u64 * CUBIC_SIZE, "cubic_buf");
|
||||
let path_coarse_wgs =
|
||||
(n_pathtag as u32 + shaders::PATH_COARSE_WG - 1) / shaders::PATH_COARSE_WG;
|
||||
recording.dispatch(
|
||||
shaders.pathseg,
|
||||
(path_coarse_wgs, 1, 1),
|
||||
[
|
||||
config_buf,
|
||||
scene_buf,
|
||||
tagmonoid_buf,
|
||||
path_bbox_buf,
|
||||
cubic_buf,
|
||||
],
|
||||
);
|
||||
let draw_reduced_buf =
|
||||
ResourceProxy::new_buf(drawobj_wgs as u64 * DRAWMONOID_SIZE, "draw_reduced_buf");
|
||||
recording.dispatch(
|
||||
shaders.draw_reduce,
|
||||
(drawobj_wgs, 1, 1),
|
||||
[config_buf, scene_buf, draw_reduced_buf],
|
||||
);
|
||||
let draw_monoid_buf =
|
||||
ResourceProxy::new_buf(n_drawobj as u64 * DRAWMONOID_SIZE, "draw_monoid_buf");
|
||||
let clip_inp_buf =
|
||||
ResourceProxy::new_buf(encoding.n_clips as u64 * CLIP_INP_SIZE, "clip_inp_buf");
|
||||
recording.dispatch(
|
||||
shaders.draw_leaf,
|
||||
(drawobj_wgs, 1, 1),
|
||||
[
|
||||
config_buf,
|
||||
scene_buf,
|
||||
draw_reduced_buf,
|
||||
path_bbox_buf,
|
||||
draw_monoid_buf,
|
||||
info_bin_data_buf,
|
||||
clip_inp_buf,
|
||||
],
|
||||
);
|
||||
recording.free_resource(draw_reduced_buf);
|
||||
let clip_el_buf =
|
||||
ResourceProxy::new_buf(encoding.n_clips as u64 * CLIP_EL_SIZE, "clip_el_buf");
|
||||
let clip_bic_buf = ResourceProxy::new_buf(
|
||||
(n_clip / shaders::CLIP_REDUCE_WG) as u64 * CLIP_BIC_SIZE,
|
||||
"clip_bic_buf",
|
||||
);
|
||||
let clip_wg_reduce = n_clip.saturating_sub(1) / shaders::CLIP_REDUCE_WG;
|
||||
if clip_wg_reduce > 0 {
|
||||
recording.dispatch(
|
||||
shaders.clip_reduce,
|
||||
(clip_wg_reduce, 1, 1),
|
||||
[
|
||||
config_buf,
|
||||
clip_inp_buf,
|
||||
path_bbox_buf,
|
||||
clip_bic_buf,
|
||||
clip_el_buf,
|
||||
],
|
||||
);
|
||||
}
|
||||
let clip_wg = (n_clip + shaders::CLIP_REDUCE_WG - 1) / shaders::CLIP_REDUCE_WG;
|
||||
let clip_bbox_buf = ResourceProxy::new_buf(n_clip as u64 * CLIP_BBOX_SIZE, "clip_bbox_buf");
|
||||
if clip_wg > 0 {
|
||||
recording.dispatch(
|
||||
shaders.clip_leaf,
|
||||
(clip_wg, 1, 1),
|
||||
[
|
||||
config_buf,
|
||||
clip_inp_buf,
|
||||
path_bbox_buf,
|
||||
clip_bic_buf,
|
||||
clip_el_buf,
|
||||
draw_monoid_buf,
|
||||
clip_bbox_buf,
|
||||
],
|
||||
);
|
||||
}
|
||||
recording.free_resource(clip_inp_buf);
|
||||
recording.free_resource(clip_bic_buf);
|
||||
recording.free_resource(clip_el_buf);
|
||||
let draw_bbox_buf =
|
||||
ResourceProxy::new_buf(n_paths as u64 * DRAW_BBOX_SIZE, "draw_bbox_buf");
|
||||
let bump_buf = BufProxy::new(BUMP_SIZE, "bump_buf");
|
||||
let width_in_bins = (config.width_in_tiles + 15) / 16;
|
||||
let height_in_bins = (config.height_in_tiles + 15) / 16;
|
||||
let bin_header_buf = ResourceProxy::new_buf(
|
||||
(256 * drawobj_wgs) as u64 * BIN_HEADER_SIZE,
|
||||
"bin_header_buf",
|
||||
);
|
||||
recording.clear_all(bump_buf);
|
||||
let bump_buf = ResourceProxy::Buf(bump_buf);
|
||||
recording.dispatch(
|
||||
shaders.binning,
|
||||
(drawobj_wgs, 1, 1),
|
||||
[
|
||||
config_buf,
|
||||
draw_monoid_buf,
|
||||
path_bbox_buf,
|
||||
clip_bbox_buf,
|
||||
draw_bbox_buf,
|
||||
bump_buf,
|
||||
info_bin_data_buf,
|
||||
bin_header_buf,
|
||||
],
|
||||
);
|
||||
recording.free_resource(draw_monoid_buf);
|
||||
recording.free_resource(path_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
|
||||
// in storage rather than workgroup memory.
|
||||
let n_path_aligned = align_up(n_paths as usize, 256);
|
||||
let path_buf = ResourceProxy::new_buf(n_path_aligned as u64 * PATH_SIZE, "path_buf");
|
||||
let path_wgs = (n_paths + shaders::PATH_BBOX_WG - 1) / shaders::PATH_BBOX_WG;
|
||||
recording.dispatch(
|
||||
shaders.tile_alloc,
|
||||
(path_wgs, 1, 1),
|
||||
[
|
||||
config_buf,
|
||||
scene_buf,
|
||||
draw_bbox_buf,
|
||||
bump_buf,
|
||||
path_buf,
|
||||
tile_buf,
|
||||
],
|
||||
);
|
||||
recording.free_resource(draw_bbox_buf);
|
||||
recording.dispatch(
|
||||
shaders.path_coarse,
|
||||
(path_coarse_wgs, 1, 1),
|
||||
[
|
||||
config_buf,
|
||||
scene_buf,
|
||||
tagmonoid_buf,
|
||||
cubic_buf,
|
||||
path_buf,
|
||||
bump_buf,
|
||||
tile_buf,
|
||||
segments_buf,
|
||||
],
|
||||
);
|
||||
recording.free_resource(tagmonoid_buf);
|
||||
recording.free_resource(cubic_buf);
|
||||
recording.dispatch(
|
||||
shaders.backdrop,
|
||||
(path_wgs, 1, 1),
|
||||
[config_buf, path_buf, tile_buf],
|
||||
);
|
||||
recording.dispatch(
|
||||
shaders.coarse,
|
||||
(width_in_bins, height_in_bins, 1),
|
||||
[
|
||||
config_buf,
|
||||
scene_buf,
|
||||
draw_monoid_buf,
|
||||
bin_header_buf,
|
||||
info_bin_data_buf,
|
||||
path_buf,
|
||||
tile_buf,
|
||||
bump_buf,
|
||||
ptcl_buf,
|
||||
],
|
||||
);
|
||||
recording.free_resource(scene_buf);
|
||||
recording.free_resource(draw_monoid_buf);
|
||||
recording.free_resource(bin_header_buf);
|
||||
recording.free_resource(path_buf);
|
||||
let out_image = ImageProxy::new(width, height, ImageFormat::Rgba8);
|
||||
self.width_in_tiles = config.width_in_tiles;
|
||||
self.height_in_tiles = config.height_in_tiles;
|
||||
self.fine = Some(FineResources {
|
||||
config_buf,
|
||||
bump_buf,
|
||||
tile_buf,
|
||||
segments_buf,
|
||||
ptcl_buf,
|
||||
gradient_image,
|
||||
info_bin_data_buf,
|
||||
out_image,
|
||||
});
|
||||
recording
|
||||
}
|
||||
|
||||
/// Run fine rasterization assuming the coarse phase succeeded.
|
||||
pub fn record_fine(&mut self, shaders: &FullShaders, recording: &mut Recording) {
|
||||
let fine = self.fine.take().unwrap();
|
||||
recording.free_resource(fine.bump_buf);
|
||||
recording.dispatch(
|
||||
shaders.fine,
|
||||
(self.width_in_tiles, self.height_in_tiles, 1),
|
||||
[
|
||||
fine.config_buf,
|
||||
fine.tile_buf,
|
||||
fine.segments_buf,
|
||||
ResourceProxy::Image(fine.out_image),
|
||||
fine.ptcl_buf,
|
||||
fine.gradient_image,
|
||||
fine.info_bin_data_buf,
|
||||
],
|
||||
);
|
||||
recording.free_resource(fine.config_buf);
|
||||
recording.free_resource(fine.tile_buf);
|
||||
recording.free_resource(fine.segments_buf);
|
||||
recording.free_resource(fine.ptcl_buf);
|
||||
recording.free_resource(fine.gradient_image);
|
||||
recording.free_resource(fine.info_bin_data_buf);
|
||||
}
|
||||
|
||||
/// Get the output image.
|
||||
///
|
||||
/// This is going away, as the caller will add the output image to the bind
|
||||
/// map.
|
||||
pub fn out_image(&self) -> ImageProxy {
|
||||
self.fine.as_ref().unwrap().out_image
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue