2022-10-25 08:53:12 +11:00
|
|
|
//! Take an encoded scene and create a graph to render it
|
|
|
|
|
|
|
|
use bytemuck::{Pod, Zeroable};
|
|
|
|
use piet_scene::Scene;
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
engine::{BufProxy, Recording},
|
|
|
|
shaders::{self, Shaders},
|
|
|
|
};
|
|
|
|
|
|
|
|
const TAG_MONOID_SIZE: u64 = 12;
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
#[derive(Clone, Copy, Zeroable, Pod)]
|
|
|
|
struct Config {
|
|
|
|
width_in_tiles: u32,
|
|
|
|
height_in_tiles: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
#[derive(Clone, Copy, Debug, Zeroable, Pod)]
|
|
|
|
pub struct PathSegment {
|
|
|
|
origin: [f32; 2],
|
|
|
|
delta: [f32; 2],
|
|
|
|
y_edge: f32,
|
|
|
|
next: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn render(scene: &Scene, shaders: &Shaders) -> (Recording, BufProxy) {
|
|
|
|
let mut recording = Recording::default();
|
|
|
|
let data = scene.data();
|
|
|
|
let n_pathtag = data.tag_stream.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 tag_data: Vec<u8> = Vec::with_capacity(pathtag_padded);
|
|
|
|
tag_data.extend(&data.tag_stream);
|
|
|
|
tag_data.resize(pathtag_padded, 0);
|
|
|
|
let pathtag_buf = recording.upload(tag_data);
|
|
|
|
let reduced_buf = BufProxy::new(pathtag_wgs as u64 * TAG_MONOID_SIZE);
|
|
|
|
// TODO: really only need pathtag_wgs - 1
|
|
|
|
recording.dispatch(
|
|
|
|
shaders.pathtag_reduce,
|
|
|
|
(pathtag_wgs as u32, 1, 1),
|
|
|
|
[pathtag_buf, reduced_buf],
|
|
|
|
);
|
|
|
|
|
|
|
|
let tagmonoid_buf =
|
|
|
|
BufProxy::new(pathtag_wgs as u64 * shaders::PATHTAG_REDUCE_WG as u64 * TAG_MONOID_SIZE);
|
|
|
|
recording.dispatch(
|
|
|
|
shaders.pathtag_scan,
|
|
|
|
(pathtag_wgs as u32, 1, 1),
|
|
|
|
[pathtag_buf, reduced_buf, tagmonoid_buf],
|
|
|
|
);
|
|
|
|
|
|
|
|
let path_coarse_wgs = (data.n_pathseg + shaders::PATH_COARSE_WG - 1) / shaders::PATH_COARSE_WG;
|
|
|
|
// The clone here is kinda BS, think about reducing copies
|
|
|
|
// Of course, we'll probably end up concatenating into a single scene binding.
|
|
|
|
let pathdata_buf = recording.upload(data.pathseg_stream.clone());
|
|
|
|
//let cubics_buf = BufProxy::new(data.n_pathseg as u64 * 32);
|
|
|
|
let config = Config {
|
|
|
|
width_in_tiles: 64,
|
|
|
|
height_in_tiles: 64,
|
|
|
|
};
|
|
|
|
let config_buf = recording.upload(bytemuck::bytes_of(&config).to_owned());
|
|
|
|
// TODO: more principled size calc
|
|
|
|
let tiles_buf = BufProxy::new(4097 * 8);
|
|
|
|
let segments_buf = BufProxy::new(256 * 24);
|
2022-10-26 03:03:13 +11:00
|
|
|
recording.clear_all(tiles_buf);
|
2022-10-25 08:53:12 +11:00
|
|
|
recording.dispatch(
|
|
|
|
shaders.path_coarse,
|
|
|
|
(path_coarse_wgs, 1, 1),
|
|
|
|
[
|
|
|
|
pathtag_buf,
|
|
|
|
tagmonoid_buf,
|
|
|
|
pathdata_buf,
|
|
|
|
config_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);
|
|
|
|
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 align_up(len: usize, alignment: u32) -> usize {
|
|
|
|
len + (len.wrapping_neg() & alignment as usize - 1)
|
|
|
|
}
|