use winit::event::WindowEvent; #[cfg_attr(rustfmt, rustfmt_skip)] #[allow(unused)] pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4 = cgmath::Matrix4::new( 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 1.0, ); #[allow(dead_code)] pub fn cast_slice(data: &[T]) -> &[u8] { use std::mem::size_of; use std::slice::from_raw_parts; unsafe { from_raw_parts(data.as_ptr() as *const u8, data.len() * size_of::()) } } #[allow(dead_code)] pub enum ShaderStage { Vertex, Fragment, Compute, } pub fn load_glsl(code: &str, stage: ShaderStage) -> Vec { let ty = match stage { ShaderStage::Vertex => glsl_to_spirv::ShaderType::Vertex, ShaderStage::Fragment => glsl_to_spirv::ShaderType::Fragment, ShaderStage::Compute => glsl_to_spirv::ShaderType::Compute, }; wgpu::read_spirv(glsl_to_spirv::compile(&code, ty).unwrap()).unwrap() } pub trait Example: 'static + Sized { fn init( sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device, ) -> (Self, Option); fn resize( &mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device, ) -> Option; fn update(&mut self, event: WindowEvent); fn render( &mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device, ) -> wgpu::CommandBuffer; } pub fn run(title: &str) { use winit::{ event, event_loop::{ControlFlow, EventLoop}, }; env_logger::init(); let event_loop = EventLoop::new(); log::info!("Initializing the window..."); #[cfg(not(feature = "gl"))] let (window, size, surface) = { let mut builder = winit::window::WindowBuilder::new(); builder = builder.with_title(title); #[cfg(windows_OFF)] //TODO { use winit::platform::windows::WindowBuilderExtWindows; builder = builder.with_no_redirection_bitmap(true); } let window = builder.build(&event_loop).unwrap(); let size = window.inner_size(); let surface = wgpu::Surface::create(&window); (window, size, surface) }; #[cfg(feature = "gl")] let (window, instance, size, surface) = { let wb = winit::WindowBuilder::new(); let cb = wgpu::glutin::ContextBuilder::new().with_vsync(true); let context = cb.build_windowed(wb, &event_loop).unwrap(); context.window().set_title(title); let hidpi_factor = context.window().hidpi_factor(); let size = context .window() .get_inner_size() .unwrap() .to_physical(hidpi_factor); let (context, window) = unsafe { context.make_current().unwrap().split() }; let instance = wgpu::Instance::new(context); let surface = instance.get_surface(); (window, instance, size, surface) }; let adapter = wgpu::Adapter::request( &wgpu::RequestAdapterOptions { power_preference: wgpu::PowerPreference::Default, }, wgpu::BackendBit::PRIMARY, ) .unwrap(); let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor { extensions: wgpu::Extensions { anisotropic_filtering: false, }, limits: wgpu::Limits::default(), }); let mut sc_desc = wgpu::SwapChainDescriptor { usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, format: wgpu::TextureFormat::Bgra8UnormSrgb, width: size.width, height: size.height, present_mode: wgpu::PresentMode::Mailbox, }; let mut swap_chain = device.create_swap_chain(&surface, &sc_desc); log::info!("Initializing the example..."); let (mut example, init_command_buf) = E::init(&sc_desc, &device); if let Some(command_buf) = init_command_buf { queue.submit(&[command_buf]); } log::info!("Entering render loop..."); event_loop.run(move |event, _, control_flow| { *control_flow = if cfg!(feature = "metal-auto-capture") { ControlFlow::Exit } else { ControlFlow::Poll }; match event { event::Event::MainEventsCleared => window.request_redraw(), event::Event::WindowEvent { event: WindowEvent::Resized(size), .. } => { log::info!("Resizing to {:?}", size); sc_desc.width = size.width; sc_desc.height = size.height; swap_chain = device.create_swap_chain(&surface, &sc_desc); let command_buf = example.resize(&sc_desc, &device); if let Some(command_buf) = command_buf { queue.submit(&[command_buf]); } } event::Event::WindowEvent { event, .. } => match event { WindowEvent::KeyboardInput { input: event::KeyboardInput { virtual_keycode: Some(event::VirtualKeyCode::Escape), state: event::ElementState::Pressed, .. }, .. } | WindowEvent::CloseRequested => { *control_flow = ControlFlow::Exit; } _ => { example.update(event); } } event::Event::RedrawRequested(_) => { let frame = swap_chain .get_next_texture() .expect("Timeout when acquiring next swap chain texture"); let command_buf = example.render(&frame, &device); queue.submit(&[command_buf]); } _ => {} } }); } // This allows treating the framework as a standalone example, // thus avoiding listing the example names in `Cargo.toml`. #[allow(dead_code)] fn main() {}