mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 12:41:30 +11:00
Add Renderer::upload_scene()
This allows rendering from raw stream data and may be temporary depending on the crate structure after the traditional piet api is removed.
This commit is contained in:
parent
c749addf6c
commit
e12b063cd3
|
@ -37,6 +37,147 @@ pub struct Encoder {
|
||||||
n_clip: u32,
|
n_clip: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct EncodedSceneRef<'a, T: Copy + Pod> {
|
||||||
|
pub transform_stream: &'a [T],
|
||||||
|
pub tag_stream: &'a [u8],
|
||||||
|
pub pathseg_stream: &'a [u8],
|
||||||
|
pub linewidth_stream: &'a [f32],
|
||||||
|
pub drawtag_stream: &'a [u32],
|
||||||
|
pub drawdata_stream: &'a [u8],
|
||||||
|
pub n_path: u32,
|
||||||
|
pub n_pathseg: u32,
|
||||||
|
pub n_clip: u32,
|
||||||
|
pub ramp_data: &'a [u32],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Copy + Pod> EncodedSceneRef<'a, T> {
|
||||||
|
/// Return a config for the element processing pipeline.
|
||||||
|
///
|
||||||
|
/// This does not include further pipeline processing. Also returns the
|
||||||
|
/// beginning of free memory.
|
||||||
|
pub fn stage_config(&self) -> (Config, usize) {
|
||||||
|
// Layout of scene buffer
|
||||||
|
let drawtag_offset = 0;
|
||||||
|
let n_drawobj = self.n_drawobj();
|
||||||
|
let n_drawobj_padded = align_up(n_drawobj, DRAW_PART_SIZE as usize);
|
||||||
|
let drawdata_offset = drawtag_offset + n_drawobj_padded * DRAWTAG_SIZE;
|
||||||
|
let trans_offset = drawdata_offset + self.drawdata_stream.len();
|
||||||
|
let n_trans = self.transform_stream.len();
|
||||||
|
let n_trans_padded = align_up(n_trans, TRANSFORM_PART_SIZE as usize);
|
||||||
|
let linewidth_offset = trans_offset + n_trans_padded * TRANSFORM_SIZE;
|
||||||
|
let n_linewidth = self.linewidth_stream.len();
|
||||||
|
let pathtag_offset = linewidth_offset + n_linewidth * LINEWIDTH_SIZE;
|
||||||
|
let n_pathtag = self.tag_stream.len();
|
||||||
|
let n_pathtag_padded = align_up(n_pathtag, PATHSEG_PART_SIZE as usize);
|
||||||
|
let pathseg_offset = pathtag_offset + n_pathtag_padded;
|
||||||
|
|
||||||
|
// Layout of memory
|
||||||
|
let mut alloc = 0;
|
||||||
|
let trans_alloc = alloc;
|
||||||
|
alloc += trans_alloc + n_trans_padded * TRANSFORM_SIZE;
|
||||||
|
let pathseg_alloc = alloc;
|
||||||
|
alloc += pathseg_alloc + self.n_pathseg as usize * PATHSEG_SIZE;
|
||||||
|
let path_bbox_alloc = alloc;
|
||||||
|
let n_path = self.n_path as usize;
|
||||||
|
alloc += path_bbox_alloc + n_path * PATH_BBOX_SIZE;
|
||||||
|
let drawmonoid_alloc = alloc;
|
||||||
|
alloc += n_drawobj_padded * DRAWMONOID_SIZE;
|
||||||
|
let anno_alloc = alloc;
|
||||||
|
alloc += n_drawobj * ANNOTATED_SIZE;
|
||||||
|
let clip_alloc = alloc;
|
||||||
|
let n_clip = self.n_clip as usize;
|
||||||
|
const CLIP_SIZE: usize = 4;
|
||||||
|
alloc += n_clip * CLIP_SIZE;
|
||||||
|
let clip_bic_alloc = alloc;
|
||||||
|
const CLIP_BIC_SIZE: usize = 8;
|
||||||
|
// This can round down, as we only reduce the prefix
|
||||||
|
alloc += (n_clip / CLIP_PART_SIZE as usize) * CLIP_BIC_SIZE;
|
||||||
|
let clip_stack_alloc = alloc;
|
||||||
|
const CLIP_EL_SIZE: usize = 20;
|
||||||
|
alloc += n_clip * CLIP_EL_SIZE;
|
||||||
|
let clip_bbox_alloc = alloc;
|
||||||
|
const CLIP_BBOX_SIZE: usize = 16;
|
||||||
|
alloc += align_up(n_clip as usize, CLIP_PART_SIZE as usize) * CLIP_BBOX_SIZE;
|
||||||
|
let draw_bbox_alloc = alloc;
|
||||||
|
alloc += n_drawobj * DRAW_BBOX_SIZE;
|
||||||
|
let drawinfo_alloc = alloc;
|
||||||
|
// TODO: not optimized; it can be accumulated during encoding or summed from drawtags
|
||||||
|
const MAX_DRAWINFO_SIZE: usize = 44;
|
||||||
|
alloc += n_drawobj * MAX_DRAWINFO_SIZE;
|
||||||
|
|
||||||
|
let config = Config {
|
||||||
|
n_elements: n_drawobj as u32,
|
||||||
|
n_pathseg: self.n_pathseg,
|
||||||
|
pathseg_alloc: pathseg_alloc as u32,
|
||||||
|
anno_alloc: anno_alloc as u32,
|
||||||
|
trans_alloc: trans_alloc as u32,
|
||||||
|
path_bbox_alloc: path_bbox_alloc as u32,
|
||||||
|
drawmonoid_alloc: drawmonoid_alloc as u32,
|
||||||
|
clip_alloc: clip_alloc as u32,
|
||||||
|
clip_bic_alloc: clip_bic_alloc as u32,
|
||||||
|
clip_stack_alloc: clip_stack_alloc as u32,
|
||||||
|
clip_bbox_alloc: clip_bbox_alloc as u32,
|
||||||
|
draw_bbox_alloc: draw_bbox_alloc as u32,
|
||||||
|
drawinfo_alloc: drawinfo_alloc as u32,
|
||||||
|
n_trans: n_trans as u32,
|
||||||
|
n_path: self.n_path,
|
||||||
|
n_clip: self.n_clip,
|
||||||
|
trans_offset: trans_offset as u32,
|
||||||
|
linewidth_offset: linewidth_offset as u32,
|
||||||
|
pathtag_offset: pathtag_offset as u32,
|
||||||
|
pathseg_offset: pathseg_offset as u32,
|
||||||
|
drawtag_offset: drawtag_offset as u32,
|
||||||
|
drawdata_offset: drawdata_offset as u32,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
(config, alloc)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_scene(&self, buf: &mut BufWrite) {
|
||||||
|
buf.extend_slice(&self.drawtag_stream);
|
||||||
|
let n_drawobj = self.drawtag_stream.len();
|
||||||
|
buf.fill_zero(padding(n_drawobj, DRAW_PART_SIZE as usize) * DRAWTAG_SIZE);
|
||||||
|
buf.extend_slice(&self.drawdata_stream);
|
||||||
|
buf.extend_slice(&self.transform_stream);
|
||||||
|
let n_trans = self.transform_stream.len();
|
||||||
|
buf.fill_zero(padding(n_trans, TRANSFORM_PART_SIZE as usize) * TRANSFORM_SIZE);
|
||||||
|
buf.extend_slice(&self.linewidth_stream);
|
||||||
|
buf.extend_slice(&self.tag_stream);
|
||||||
|
let n_pathtag = self.tag_stream.len();
|
||||||
|
buf.fill_zero(padding(n_pathtag, PATHSEG_PART_SIZE as usize));
|
||||||
|
buf.extend_slice(&self.pathseg_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The number of draw objects in the draw object stream.
|
||||||
|
pub(crate) fn n_drawobj(&self) -> usize {
|
||||||
|
self.drawtag_stream.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The number of paths.
|
||||||
|
pub(crate) fn n_path(&self) -> u32 {
|
||||||
|
self.n_path
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The number of path segments.
|
||||||
|
pub(crate) fn n_pathseg(&self) -> u32 {
|
||||||
|
self.n_pathseg
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn n_transform(&self) -> usize {
|
||||||
|
self.transform_stream.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The number of tags in the path stream.
|
||||||
|
pub(crate) fn n_pathtag(&self) -> usize {
|
||||||
|
self.tag_stream.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn n_clip(&self) -> u32 {
|
||||||
|
self.n_clip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A scene fragment encoding a glyph.
|
/// A scene fragment encoding a glyph.
|
||||||
///
|
///
|
||||||
/// This is a reduced version of the full encoder.
|
/// This is a reduced version of the full encoder.
|
||||||
|
|
|
@ -8,9 +8,11 @@ pub mod stages;
|
||||||
pub mod test_scenes;
|
pub mod test_scenes;
|
||||||
mod text;
|
mod text;
|
||||||
|
|
||||||
|
use bytemuck::Pod;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
pub use blend::{Blend, BlendMode, CompositionMode};
|
pub use blend::{Blend, BlendMode, CompositionMode};
|
||||||
|
pub use encoder::EncodedSceneRef;
|
||||||
pub use render_ctx::PietGpuRenderContext;
|
pub use render_ctx::PietGpuRenderContext;
|
||||||
pub use gradient::Colrv1RadialGradient;
|
pub use gradient::Colrv1RadialGradient;
|
||||||
|
|
||||||
|
@ -406,6 +408,61 @@ impl Renderer {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn upload_scene<T: Copy + Pod>(
|
||||||
|
&mut self,
|
||||||
|
scene: &EncodedSceneRef<T>,
|
||||||
|
buf_ix: usize,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let (mut config, mut alloc) = scene.stage_config();
|
||||||
|
let n_drawobj = scene.n_drawobj();
|
||||||
|
// TODO: be more consistent in size types
|
||||||
|
let n_path = scene.n_path() as usize;
|
||||||
|
self.n_paths = n_path;
|
||||||
|
self.n_transform = scene.n_transform();
|
||||||
|
self.n_drawobj = scene.n_drawobj();
|
||||||
|
self.n_pathseg = scene.n_pathseg() as usize;
|
||||||
|
self.n_pathtag = scene.n_pathtag();
|
||||||
|
self.n_clip = scene.n_clip();
|
||||||
|
|
||||||
|
// These constants depend on encoding and may need to be updated.
|
||||||
|
// Perhaps we can plumb these from piet-gpu-derive?
|
||||||
|
const PATH_SIZE: usize = 12;
|
||||||
|
const BIN_SIZE: usize = 8;
|
||||||
|
let width_in_tiles = self.width / TILE_W;
|
||||||
|
let height_in_tiles = self.height / TILE_H;
|
||||||
|
let tile_base = alloc;
|
||||||
|
alloc += ((n_path + 3) & !3) * PATH_SIZE;
|
||||||
|
let bin_base = alloc;
|
||||||
|
alloc += ((n_drawobj + 255) & !255) * BIN_SIZE;
|
||||||
|
let ptcl_base = alloc;
|
||||||
|
alloc += width_in_tiles * height_in_tiles * PTCL_INITIAL_ALLOC;
|
||||||
|
|
||||||
|
config.width_in_tiles = width_in_tiles as u32;
|
||||||
|
config.height_in_tiles = height_in_tiles as u32;
|
||||||
|
config.tile_alloc = tile_base as u32;
|
||||||
|
config.bin_alloc = bin_base as u32;
|
||||||
|
config.ptcl_alloc = ptcl_base as u32;
|
||||||
|
unsafe {
|
||||||
|
// TODO: reallocate scene buffer if size is inadequate
|
||||||
|
{
|
||||||
|
let mut mapped_scene = self.scene_bufs[buf_ix].map_write(..)?;
|
||||||
|
scene.write_scene(&mut mapped_scene);
|
||||||
|
}
|
||||||
|
self.config_bufs[buf_ix].write(&[config])?;
|
||||||
|
self.memory_buf_host[buf_ix].write(&[alloc as u32, 0 /* Overflow flag */])?;
|
||||||
|
|
||||||
|
// Upload gradient data.
|
||||||
|
if !scene.ramp_data.is_empty() {
|
||||||
|
assert!(
|
||||||
|
self.gradient_bufs[buf_ix].size() as usize
|
||||||
|
>= std::mem::size_of_val(&*scene.ramp_data)
|
||||||
|
);
|
||||||
|
self.gradient_bufs[buf_ix].write(scene.ramp_data)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn record(&self, cmd_buf: &mut CmdBuf, query_pool: &QueryPool, buf_ix: usize) {
|
pub unsafe fn record(&self, cmd_buf: &mut CmdBuf, query_pool: &QueryPool, buf_ix: usize) {
|
||||||
cmd_buf.copy_buffer(&self.config_bufs[buf_ix], &self.config_buf);
|
cmd_buf.copy_buffer(&self.config_bufs[buf_ix], &self.config_buf);
|
||||||
cmd_buf.copy_buffer(&self.memory_buf_host[buf_ix], &self.memory_buf_dev);
|
cmd_buf.copy_buffer(&self.memory_buf_host[buf_ix], &self.memory_buf_dev);
|
||||||
|
|
|
@ -57,7 +57,7 @@ fn main() -> Result<(), Error> {
|
||||||
.map(|_| session.create_semaphore())
|
.map(|_| session.create_semaphore())
|
||||||
.collect::<Result<Vec<_>, Error>>()?;
|
.collect::<Result<Vec<_>, Error>>()?;
|
||||||
let query_pools = (0..NUM_FRAMES)
|
let query_pools = (0..NUM_FRAMES)
|
||||||
.map(|_| session.create_query_pool(8))
|
.map(|_| session.create_query_pool(12))
|
||||||
.collect::<Result<Vec<_>, Error>>()?;
|
.collect::<Result<Vec<_>, Error>>()?;
|
||||||
let mut cmd_bufs: [Option<CmdBuf>; NUM_FRAMES] = Default::default();
|
let mut cmd_bufs: [Option<CmdBuf>; NUM_FRAMES] = Default::default();
|
||||||
let mut submitted: [Option<SubmittedCmdBuf>; NUM_FRAMES] = Default::default();
|
let mut submitted: [Option<SubmittedCmdBuf>; NUM_FRAMES] = Default::default();
|
||||||
|
@ -99,72 +99,26 @@ fn main() -> Result<(), Error> {
|
||||||
if !ts.is_empty() {
|
if !ts.is_empty() {
|
||||||
info_string = format!(
|
info_string = format!(
|
||||||
"{:.3}ms :: e:{:.3}ms|alloc:{:.3}ms|cp:{:.3}ms|bd:{:.3}ms|bin:{:.3}ms|cr:{:.3}ms|r:{:.3}ms",
|
"{:.3}ms :: e:{:.3}ms|alloc:{:.3}ms|cp:{:.3}ms|bd:{:.3}ms|bin:{:.3}ms|cr:{:.3}ms|r:{:.3}ms",
|
||||||
ts[6] * 1e3,
|
ts[10] * 1e3,
|
||||||
ts[0] * 1e3,
|
ts[0] * 1e3,
|
||||||
(ts[1] - ts[0]) * 1e3,
|
(ts[1] - ts[0]) * 1e3,
|
||||||
(ts[2] - ts[1]) * 1e3,
|
(ts[2] - ts[1]) * 1e3,
|
||||||
(ts[3] - ts[2]) * 1e3,
|
|
||||||
(ts[4] - ts[3]) * 1e3,
|
(ts[4] - ts[3]) * 1e3,
|
||||||
(ts[5] - ts[4]) * 1e3,
|
|
||||||
(ts[6] - ts[5]) * 1e3,
|
(ts[6] - ts[5]) * 1e3,
|
||||||
|
(ts[8] - ts[7]) * 1e3,
|
||||||
|
(ts[10] - ts[9]) * 1e3,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ctx = PietGpuRenderContext::new();
|
let mut ctx = PietGpuRenderContext::new();
|
||||||
if let Some(input) = matches.value_of("INPUT") {
|
|
||||||
let mut scale = matches
|
|
||||||
.value_of("scale")
|
|
||||||
.map(|scale| scale.parse().unwrap())
|
|
||||||
.unwrap_or(8.0);
|
|
||||||
if matches.is_present("flip") {
|
|
||||||
scale = -scale;
|
|
||||||
}
|
|
||||||
test_scenes::render_svg(&mut ctx, input, scale);
|
|
||||||
} else {
|
|
||||||
use piet_gpu::{Blend, BlendMode::*, CompositionMode::*};
|
|
||||||
let blends = [
|
|
||||||
Blend::new(Normal, SrcOver),
|
|
||||||
Blend::new(Multiply, SrcOver),
|
|
||||||
Blend::new(Screen, SrcOver),
|
|
||||||
Blend::new(Overlay, SrcOver),
|
|
||||||
Blend::new(Darken, SrcOver),
|
|
||||||
Blend::new(Lighten, SrcOver),
|
|
||||||
Blend::new(ColorDodge, SrcOver),
|
|
||||||
Blend::new(ColorBurn, SrcOver),
|
|
||||||
Blend::new(HardLight, SrcOver),
|
|
||||||
Blend::new(SoftLight, SrcOver),
|
|
||||||
Blend::new(Difference, SrcOver),
|
|
||||||
Blend::new(Exclusion, SrcOver),
|
|
||||||
Blend::new(Hue, SrcOver),
|
|
||||||
Blend::new(Saturation, SrcOver),
|
|
||||||
Blend::new(Color, SrcOver),
|
|
||||||
Blend::new(Luminosity, SrcOver),
|
|
||||||
Blend::new(Normal, Clear),
|
|
||||||
Blend::new(Normal, Copy),
|
|
||||||
Blend::new(Normal, Dest),
|
|
||||||
Blend::new(Normal, SrcOver),
|
|
||||||
Blend::new(Normal, DestOver),
|
|
||||||
Blend::new(Normal, SrcIn),
|
|
||||||
Blend::new(Normal, DestIn),
|
|
||||||
Blend::new(Normal, SrcOut),
|
|
||||||
Blend::new(Normal, DestOut),
|
|
||||||
Blend::new(Normal, SrcAtop),
|
|
||||||
Blend::new(Normal, DestAtop),
|
|
||||||
Blend::new(Normal, Xor),
|
|
||||||
Blend::new(Normal, Plus),
|
|
||||||
];
|
|
||||||
let blend = blends[mode % blends.len()];
|
|
||||||
test_scenes::render_blend_test(&mut ctx, current_frame, blend);
|
|
||||||
info_string = format!("{:?}", blend);
|
|
||||||
}
|
|
||||||
render_info_string(&mut ctx, &info_string);
|
render_info_string(&mut ctx, &info_string);
|
||||||
|
|
||||||
ctx = PietGpuRenderContext::new();
|
ctx = PietGpuRenderContext::new();
|
||||||
test_scene1_old(&mut ctx);
|
test_scene1_old(&mut ctx);
|
||||||
let mut encoded_scene_old = ctx.encoded_scene();
|
//let mut encoded_scene_old = ctx.encoded_scene();
|
||||||
let ramp_data = ctx.get_ramp_data();
|
// let ramp_data = ctx.get_ramp_data();
|
||||||
encoded_scene_old.ramp_data = &ramp_data;
|
//encoded_scene_old.ramp_data = &ramp_data;
|
||||||
test_scene1(&mut scene, &mut rcx);
|
test_scene1(&mut scene, &mut rcx);
|
||||||
let encoded_scene = scene_to_encoded_scene(&scene, &rcx);
|
let encoded_scene = scene_to_encoded_scene(&scene, &rcx);
|
||||||
// println!("{:?}\n============\n{:?}", encoded_scene_old, encoded_scene);
|
// println!("{:?}\n============\n{:?}", encoded_scene_old, encoded_scene);
|
||||||
|
|
Loading…
Reference in a new issue