vello/piet-gpu/bin/winit.rs
Chad Brokaw f19dbdb1b5 Update piet-scene to depend on peniko
This adds a new dependency on peniko, reintroduces kurbo for geometry (!), removes the now defunct types from piet-scene and updates all the test scenes to use the new types.
2022-11-22 14:49:51 -05:00

197 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::{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 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 {
let mut builder = SceneBuilder::for_scene(&mut scene);
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) {
println!("error in uploading: {}", e);
}
} else {
let mut builder = SceneBuilder::for_scene(&mut scene);
const N_SAMPLES: usize = 6;
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),
3 => samples::render_brush_transform(&mut builder, current_frame),
4 => samples::render_funky_paths(&mut builder),
_ => 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) {
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::kurbo::Affine::translate((110.0, 50.0)),
info,
);
}