vello/piet-gpu/bin/winit.rs
Chad Brokaw 782e7d51d2 Remove piet API & replace w/ fragments
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.
2022-10-19 15:19:20 -04:00

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,
);
}