mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 20:51:29 +11:00
782e7d51d2
Removes the dependency on the piet crate and replaces all uses with the scene crate. Also does some cleanup of the scene API, renaming some types and moving them all to the crate root for better ergonomics.
198 lines
7.8 KiB
Rust
198 lines
7.8 KiB
Rust
use piet_gpu::{samples, PicoSvg, RenderDriver, Renderer, SimpleText};
|
|
use piet_gpu_hal::{Error, ImageLayout, Instance, InstanceFlags, Session};
|
|
use piet_scene::{ResourceContext, Scene, SceneBuilder};
|
|
|
|
use clap::{App, Arg};
|
|
|
|
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
|
|
|
use winit::{
|
|
event::{Event, WindowEvent},
|
|
event_loop::{ControlFlow, EventLoop},
|
|
window::WindowBuilder,
|
|
};
|
|
|
|
const NUM_FRAMES: usize = 2;
|
|
|
|
const WIDTH: usize = 2048;
|
|
const HEIGHT: usize = 1536;
|
|
|
|
fn main() -> Result<(), Error> {
|
|
let matches = App::new("piet-gpu test")
|
|
.arg(Arg::with_name("INPUT").index(1))
|
|
.arg(Arg::with_name("flip").short('f').long("flip"))
|
|
.arg(
|
|
Arg::with_name("scale")
|
|
.short('s')
|
|
.long("scale")
|
|
.takes_value(true),
|
|
)
|
|
.get_matches();
|
|
|
|
// Collect SVG if input
|
|
let svg = match matches.value_of("INPUT") {
|
|
Some(file) => {
|
|
let mut scale = matches
|
|
.value_of("scale")
|
|
.map(|scale| scale.parse().unwrap())
|
|
.unwrap_or(8.0);
|
|
if matches.is_present("flip") {
|
|
scale = -scale;
|
|
}
|
|
let xml_str = std::fs::read_to_string(file).unwrap();
|
|
let start = std::time::Instant::now();
|
|
let svg = PicoSvg::load(&xml_str, scale).unwrap();
|
|
println!("parsing time: {:?}", start.elapsed());
|
|
Some(svg)
|
|
}
|
|
None => None,
|
|
};
|
|
|
|
let event_loop = EventLoop::new();
|
|
let window = WindowBuilder::new()
|
|
.with_inner_size(winit::dpi::LogicalSize {
|
|
width: (WIDTH / 2) as f64,
|
|
height: (HEIGHT / 2) as f64,
|
|
})
|
|
.with_resizable(false) // currently not supported
|
|
.build(&event_loop)?;
|
|
|
|
let instance = Instance::new(InstanceFlags::default())?;
|
|
let mut info_string = "info".to_string();
|
|
let mut scene = Scene::default();
|
|
let mut rcx = ResourceContext::default();
|
|
let mut simple_text = piet_gpu::SimpleText::new();
|
|
unsafe {
|
|
let display_handle = window.raw_display_handle();
|
|
let window_handle = window.raw_window_handle();
|
|
let surface = instance.surface(display_handle, window_handle)?;
|
|
let device = instance.device()?;
|
|
let mut swapchain = instance.swapchain(WIDTH / 2, HEIGHT / 2, &device, &surface)?;
|
|
let session = Session::new(device);
|
|
|
|
let mut current_frame = 0;
|
|
let present_semaphores = (0..NUM_FRAMES)
|
|
.map(|_| session.create_semaphore())
|
|
.collect::<Result<Vec<_>, Error>>()?;
|
|
|
|
let renderer = Renderer::new(&session, WIDTH, HEIGHT, NUM_FRAMES)?;
|
|
let mut render_driver = RenderDriver::new(&session, NUM_FRAMES, renderer);
|
|
let mut sample_index = 0usize;
|
|
|
|
event_loop.run(move |event, _, control_flow| {
|
|
*control_flow = ControlFlow::Poll; // `ControlFlow::Wait` if only re-render on event
|
|
|
|
match event {
|
|
Event::WindowEvent { event, window_id } if window_id == window.id() => {
|
|
use winit::event::{ElementState, VirtualKeyCode};
|
|
match event {
|
|
WindowEvent::CloseRequested => {
|
|
*control_flow = ControlFlow::Exit;
|
|
}
|
|
WindowEvent::KeyboardInput { input, .. } => {
|
|
if input.state == ElementState::Pressed {
|
|
match input.virtual_keycode {
|
|
Some(VirtualKeyCode::Left) => {
|
|
sample_index = sample_index.saturating_sub(1)
|
|
}
|
|
Some(VirtualKeyCode::Right) => {
|
|
sample_index = sample_index.saturating_add(1)
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
_ => (),
|
|
}
|
|
}
|
|
Event::MainEventsCleared => {
|
|
window.request_redraw();
|
|
}
|
|
Event::RedrawRequested(window_id) if window_id == window.id() => {
|
|
let frame_idx = current_frame % NUM_FRAMES;
|
|
|
|
if current_frame >= NUM_FRAMES {
|
|
let stats = render_driver.get_timing_stats(&session, frame_idx);
|
|
info_string = stats.short_summary();
|
|
}
|
|
|
|
if let Some(svg) = &svg {
|
|
rcx.advance();
|
|
let mut builder = SceneBuilder::for_scene(&mut scene, &mut rcx);
|
|
samples::render_svg(&mut builder, svg, false);
|
|
render_info(&mut simple_text, &mut builder, &info_string);
|
|
builder.finish();
|
|
if let Err(e) = render_driver.upload_scene(&session, &scene, &rcx) {
|
|
println!("error in uploading: {}", e);
|
|
}
|
|
} else {
|
|
rcx.advance();
|
|
let mut builder = SceneBuilder::for_scene(&mut scene, &mut rcx);
|
|
|
|
const N_SAMPLES: usize = 4;
|
|
match sample_index % N_SAMPLES {
|
|
0 => samples::render_anim_frame(
|
|
&mut builder,
|
|
&mut simple_text,
|
|
current_frame,
|
|
),
|
|
1 => samples::render_blend_grid(&mut builder),
|
|
2 => samples::render_tiger(&mut builder, false),
|
|
_ => samples::render_scene(&mut builder),
|
|
}
|
|
render_info(&mut simple_text, &mut builder, &info_string);
|
|
builder.finish();
|
|
if let Err(e) = render_driver.upload_scene(&session, &scene, &rcx) {
|
|
println!("error in uploading: {}", e);
|
|
}
|
|
}
|
|
|
|
let (image_idx, acquisition_semaphore) = swapchain.next().unwrap();
|
|
let swap_image = swapchain.image(image_idx);
|
|
render_driver.run_coarse(&session).unwrap();
|
|
let target = render_driver.record_fine(&session).unwrap();
|
|
let cmd_buf = target.cmd_buf;
|
|
|
|
// Image -> Swapchain
|
|
cmd_buf.image_barrier(
|
|
&swap_image,
|
|
ImageLayout::Undefined,
|
|
ImageLayout::BlitDst,
|
|
);
|
|
cmd_buf.blit_image(target.image, &swap_image);
|
|
cmd_buf.image_barrier(&swap_image, ImageLayout::BlitDst, ImageLayout::Present);
|
|
render_driver
|
|
.submit(
|
|
&session,
|
|
&[&acquisition_semaphore],
|
|
&[&present_semaphores[frame_idx]],
|
|
)
|
|
.unwrap();
|
|
|
|
swapchain
|
|
.present(image_idx, &[&present_semaphores[frame_idx]])
|
|
.unwrap();
|
|
|
|
render_driver.next_buffer();
|
|
current_frame += 1;
|
|
}
|
|
Event::LoopDestroyed => {
|
|
render_driver.wait_all(&session);
|
|
}
|
|
_ => (),
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
fn render_info(simple_text: &mut SimpleText, sb: &mut SceneBuilder, info: &str) {
|
|
simple_text.add(
|
|
sb,
|
|
None,
|
|
40.0,
|
|
None,
|
|
piet_scene::Affine::translate(110.0, 50.0),
|
|
info,
|
|
);
|
|
}
|