Renamed clear_color to base_color; addressed review comments

This commit is contained in:
Arman Uguray 2023-03-02 14:29:06 -08:00
parent 05fa8c7c39
commit 3bbf108df5
9 changed files with 54 additions and 73 deletions

View file

@ -92,15 +92,15 @@ async fn render(mut scenes: SceneSet, index: usize, args: &Args) -> Result<()> {
let mut builder = SceneBuilder::for_fragment(&mut fragment); let mut builder = SceneBuilder::for_fragment(&mut fragment);
let example_scene = &mut scenes.scenes[index]; let example_scene = &mut scenes.scenes[index];
let mut text = SimpleText::new(); let mut text = SimpleText::new();
let mut params = SceneParams { let mut scene_params = SceneParams {
time: args.time.unwrap_or(0.), time: args.time.unwrap_or(0.),
text: &mut text, text: &mut text,
resolution: None, resolution: None,
}; };
(example_scene.function)(&mut builder, &mut params); (example_scene.function)(&mut builder, &mut scene_params);
builder.finish(); builder.finish();
let mut transform = Affine::IDENTITY; let mut transform = Affine::IDENTITY;
let (width, height) = if let Some(resolution) = params.resolution { let (width, height) = if let Some(resolution) = scene_params.resolution {
let ratio = resolution.x / resolution.y; let ratio = resolution.x / resolution.y;
let (new_width, new_height) = match (args.x_resolution, args.y_resolution) { let (new_width, new_height) = match (args.x_resolution, args.y_resolution) {
(None, None) => (resolution.x.ceil() as u32, resolution.y.ceil() as u32), (None, None) => (resolution.x.ceil() as u32, resolution.y.ceil() as u32),
@ -126,8 +126,11 @@ async fn render(mut scenes: SceneSet, index: usize, args: &Args) -> Result<()> {
(Some(x), Some(y)) => (x.try_into()?, y.try_into()?), (Some(x), Some(y)) => (x.try_into()?, y.try_into()?),
} }
}; };
let params = vello::RenderParams { let render_params = vello::RenderParams {
clear_color: vello::peniko::Color::BLACK, base_color: args
.args
.get_base_color()?
.unwrap_or(vello::peniko::Color::BLACK),
width, width,
height, height,
}; };
@ -152,7 +155,7 @@ async fn render(mut scenes: SceneSet, index: usize, args: &Args) -> Result<()> {
}); });
let view = target.create_view(&wgpu::TextureViewDescriptor::default()); let view = target.create_view(&wgpu::TextureViewDescriptor::default());
renderer renderer
.render_to_texture(&device, &queue, &scene, &view, &params) .render_to_texture(&device, &queue, &scene, &view, &render_params)
.or_else(|_| bail!("Got non-Send/Sync error from rendering"))?; .or_else(|_| bail!("Got non-Send/Sync error from rendering"))?;
// (width * 4).next_multiple_of(256) // (width * 4).next_multiple_of(256)
let padded_byte_width = { let padded_byte_width = {

View file

@ -5,7 +5,7 @@ mod svg;
mod test_scenes; mod test_scenes;
use std::path::PathBuf; use std::path::PathBuf;
use anyhow::Result; use anyhow::{anyhow, Result};
use clap::{Args, Subcommand}; use clap::{Args, Subcommand};
use download::Download; use download::Download;
pub use simple_text::SimpleText; pub use simple_text::SimpleText;
@ -13,7 +13,7 @@ pub use simple_text::SimpleText;
pub use svg::{default_scene, scene_from_files}; pub use svg::{default_scene, scene_from_files};
pub use test_scenes::test_scenes; pub use test_scenes::test_scenes;
use vello::{kurbo::Vec2, SceneBuilder}; use vello::{kurbo::Vec2, peniko::Color, SceneBuilder};
pub struct SceneParams<'a> { pub struct SceneParams<'a> {
pub time: f64, pub time: f64,
@ -46,6 +46,12 @@ pub struct Arguments {
#[arg(help_heading = "Scene Selection", global(false))] #[arg(help_heading = "Scene Selection", global(false))]
/// The svg files paths to render /// The svg files paths to render
svgs: Option<Vec<PathBuf>>, svgs: Option<Vec<PathBuf>>,
#[arg(help_heading = "Render Parameters")]
#[arg(long, global(false))]
/// The base color applied as the blend background to the rasterizer.
/// Format is CSS style hexidecimal (#RGB, #RGBA, #RRGGBB, #RRGGBBAA) or
/// an SVG color name such as "aliceblue"
base_color: Option<String>,
#[clap(subcommand)] #[clap(subcommand)]
command: Option<Command>, command: Option<Command>,
} }
@ -79,6 +85,17 @@ impl Arguments {
.map(Some) .map(Some)
} }
} }
pub fn get_base_color(&self) -> Result<Option<Color>> {
self.base_color.as_ref().map_or_else(
|| Ok(None),
|s| {
Color::parse(&s)
.ok_or_else(|| anyhow!("malformed color: {}", s))
.map(Some)
},
)
}
} }
impl Command { impl Command {

View file

@ -47,7 +47,7 @@ fn render_scenes(
for scene in &mut scenes { for scene in &mut scenes {
let gpu_image = gpu_images.get(&scene.1).unwrap(); let gpu_image = gpu_images.get(&scene.1).unwrap();
let params = vello::RenderParams { let params = vello::RenderParams {
clear_color: vello::peniko::Color::AQUAMARINE, base_color: vello::peniko::Color::AQUAMARINE,
width: gpu_image.size.x as u32, width: gpu_image.size.x as u32,
height: gpu_image.size.y as u32, height: gpu_image.size.y as u32,
}; };

View file

@ -17,10 +17,7 @@
use std::time::Instant; use std::time::Instant;
use anyhow::Result; use anyhow::Result;
use clap::{ use clap::{CommandFactory, Parser};
builder::{PossibleValuesParser, TypedValueParser as _},
CommandFactory, Parser,
};
use scenes::{SceneParams, SceneSet, SimpleText}; use scenes::{SceneParams, SceneSet, SimpleText};
use vello::SceneFragment; use vello::SceneFragment;
use vello::{ use vello::{
@ -53,52 +50,18 @@ struct Args {
/// Switch between scenes with left and right arrow keys /// Switch between scenes with left and right arrow keys
#[arg(long)] #[arg(long)]
scene: Option<i32>, scene: Option<i32>,
#[arg( /// The base color used as the
long,
default_value_t = ClearColor::Black,
value_parser = PossibleValuesParser::new(["black", "white", "aquamarine", "crimson"])
.map(|s| s.parse::<ClearColor>().unwrap())
)]
clear_color: ClearColor,
#[command(flatten)] #[command(flatten)]
args: scenes::Arguments, args: scenes::Arguments,
} }
#[derive(Debug, Clone)] async fn run(
enum ClearColor { event_loop: EventLoop<UserEvent>,
Black, window: Window,
White, args: Args,
Crimson, base_color: Color,
Aquamarine, mut scenes: SceneSet,
} ) {
impl std::fmt::Display for ClearColor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Self::Black => "black",
Self::White => "white",
Self::Crimson => "crimson",
Self::Aquamarine => "aquamarine",
};
s.fmt(f)
}
}
impl std::str::FromStr for ClearColor {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"black" => Ok(Self::Black),
"white" => Ok(Self::White),
"crimson" => Ok(Self::Crimson),
"aquamarine" => Ok(Self::Aquamarine),
_ => Err(format!("invalid color: {s}")),
}
}
}
async fn run(event_loop: EventLoop<UserEvent>, window: Window, args: Args, mut scenes: SceneSet) {
use winit::{event::*, event_loop::ControlFlow}; use winit::{event::*, event_loop::ControlFlow};
let mut render_cx = RenderContext::new().unwrap(); let mut render_cx = RenderContext::new().unwrap();
let size = window.inner_size(); let size = window.inner_size();
@ -120,12 +83,6 @@ async fn run(event_loop: EventLoop<UserEvent>, window: Window, args: Args, mut s
if let Some(set_scene) = args.scene { if let Some(set_scene) = args.scene {
scene_ix = set_scene; scene_ix = set_scene;
} }
let clear_color = match args.clear_color {
ClearColor::Black => Color::BLACK,
ClearColor::White => Color::WHITE,
ClearColor::Crimson => Color::CRIMSON,
ClearColor::Aquamarine => Color::AQUAMARINE,
};
let mut prev_scene_ix = scene_ix - 1; let mut prev_scene_ix = scene_ix - 1;
event_loop.run(move |event, _, control_flow| match event { event_loop.run(move |event, _, control_flow| match event {
Event::WindowEvent { Event::WindowEvent {
@ -207,7 +164,7 @@ async fn run(event_loop: EventLoop<UserEvent>, window: Window, args: Args, mut s
let device_handle = &render_cx.devices[surface.dev_id]; let device_handle = &render_cx.devices[surface.dev_id];
let render_params = vello::RenderParams { let render_params = vello::RenderParams {
clear_color, base_color,
width, width,
height, height,
}; };
@ -300,6 +257,7 @@ fn main() -> Result<()> {
env_logger::init(); env_logger::init();
let args = Args::parse(); let args = Args::parse();
let scenes = args.args.select_scene_set(|| Args::command())?; let scenes = args.args.select_scene_set(|| Args::command())?;
let base_color = args.args.get_base_color()?.unwrap_or(Color::BLACK);
if let Some(scenes) = scenes { if let Some(scenes) = scenes {
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
{ {
@ -317,7 +275,7 @@ fn main() -> Result<()> {
.with_title("Vello demo") .with_title("Vello demo")
.build(&event_loop) .build(&event_loop)
.unwrap(); .unwrap();
pollster::block_on(run(event_loop, window, args, scenes)); pollster::block_on(run(event_loop, window, args, base_color, scenes));
} }
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
{ {
@ -337,7 +295,7 @@ fn main() -> Result<()> {
.and_then(|doc| doc.body()) .and_then(|doc| doc.body())
.and_then(|body| body.append_child(&web_sys::Element::from(canvas)).ok()) .and_then(|body| body.append_child(&web_sys::Element::from(canvas)).ok())
.expect("couldn't append canvas to document body"); .expect("couldn't append canvas to document body");
wasm_bindgen_futures::spawn_local(run(event_loop, window, args, scenes)); wasm_bindgen_futures::spawn_local(run(event_loop, window, args, base_color, scenes));
} }
} }
Ok(()) Ok(())

View file

@ -188,7 +188,7 @@ fn main(
#ifdef full #ifdef full
var rgba: array<vec4<f32>, PIXELS_PER_THREAD>; var rgba: array<vec4<f32>, PIXELS_PER_THREAD>;
for (var i = 0u; i < PIXELS_PER_THREAD; i += 1u) { for (var i = 0u; i < PIXELS_PER_THREAD; i += 1u) {
rgba[i] = unpack4x8unorm(config.clear_color).wzyx; rgba[i] = unpack4x8unorm(config.base_color).wzyx;
} }
var blend_stack: array<array<u32, PIXELS_PER_THREAD>, BLEND_STACK_SPLIT>; var blend_stack: array<array<u32, PIXELS_PER_THREAD>, BLEND_STACK_SPLIT>;
var clip_depth = 0u; var clip_depth = 0u;

View file

@ -10,7 +10,7 @@ struct Config {
// The initial color applied to the pixels in a tile during the fine stage. // The initial color applied to the pixels in a tile during the fine stage.
// This is only used in the full pipeline. The format is packed RGBA8 in MSB // This is only used in the full pipeline. The format is packed RGBA8 in MSB
// order. // order.
clear_color: u32, base_color: u32,
n_drawobj: u32, n_drawobj: u32,
n_path: u32, n_path: u32,

View file

@ -48,7 +48,8 @@ pub struct Layout {
pub linewidth_base: u32, pub linewidth_base: u32,
} }
/// Scene configuration. /// 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)] #[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
#[repr(C)] #[repr(C)]
pub struct Config { pub struct Config {
@ -60,8 +61,8 @@ pub struct Config {
pub target_width: u32, pub target_width: u32,
/// Height of the target in pixels. /// Height of the target in pixels.
pub target_height: u32, pub target_height: u32,
/// The initial background color applied to the target /// The base background color applied to the target before any blends.
pub clear_color: u32, pub base_color: u32,
/// Layout of packed scene data. /// Layout of packed scene data.
pub layout: Layout, pub layout: Layout,
/// Size of binning buffer allocation (in u32s). /// Size of binning buffer allocation (in u32s).

View file

@ -56,7 +56,7 @@ pub struct Renderer {
pub struct RenderParams { pub struct RenderParams {
/// The background color applied to the target. This value is only applicable to the full /// The background color applied to the target. This value is only applicable to the full
/// pipeline. /// pipeline.
pub clear_color: peniko::Color, pub base_color: peniko::Color,
/// Dimensions of the rasterization target /// Dimensions of the rasterization target
pub width: u32, pub width: u32,
@ -64,7 +64,7 @@ pub struct RenderParams {
} }
impl Renderer { impl Renderer {
/// Creates a new renderer for the specified device with default options. /// Creates a new renderer for the specified device.
pub fn new(device: &Device) -> Result<Self> { pub fn new(device: &Device) -> Result<Self> {
let mut engine = Engine::new(); let mut engine = Engine::new();
let shaders = shaders::full_shaders(device, &mut engine)?; let shaders = shaders::full_shaders(device, &mut engine)?;

View file

@ -55,6 +55,8 @@ const BIN_HEADER_SIZE: u64 = 8;
const TILE_SIZE: u64 = 8; const TILE_SIZE: u64 = 8;
const SEGMENT_SIZE: u64 = 24; const SEGMENT_SIZE: u64 = 24;
// This data structure must be kept in sync with encoding::Config and the definition in
// shaders/shared/config.wgsl.
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] #[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
struct Config { struct Config {
@ -62,7 +64,7 @@ struct Config {
height_in_tiles: u32, height_in_tiles: u32,
target_width: u32, target_width: u32,
target_height: u32, target_height: u32,
clear_color: u32, base_color: u32,
n_drawobj: u32, n_drawobj: u32,
n_path: u32, n_path: u32,
n_clip: u32, n_clip: u32,
@ -264,7 +266,7 @@ impl Render {
height_in_tiles: new_height / 16, height_in_tiles: new_height / 16,
target_width: params.width, target_width: params.width,
target_height: params.height, target_height: params.height,
clear_color: params.clear_color.to_premul_u32(), base_color: params.base_color.to_premul_u32(),
binning_size: self.binning_info_size - info_size, binning_size: self.binning_info_size - info_size,
tiles_size: self.tiles_size, tiles_size: self.tiles_size,
segments_size: self.segments_size, segments_size: self.segments_size,