use simple_wgpu::{ ColorAttachment, CommandEncoder, Context, DrawCall, RenderPipelineBuilder, RenderTexture, Shader, }; use wgpu::include_wgsl; use winit::{ event::{Event, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::Window, }; async fn run(event_loop: EventLoop<()>, window: Window) { let size = window.inner_size(); let instance = wgpu::Instance::default(); let surface = unsafe { instance.create_surface(&window) }.unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { power_preference: wgpu::PowerPreference::default(), force_fallback_adapter: false, // Request an adapter which can render to our surface compatible_surface: Some(&surface), }) .await .expect("Failed to find an appropriate adapter"); // Create the logical device and command queue let (device, queue) = adapter .request_device( &wgpu::DeviceDescriptor { label: None, features: wgpu::Features::empty(), // Make sure we use the texture resolution limits from the adapter, so we can support images the size of the swapchain. limits: wgpu::Limits::downlevel_webgl2_defaults() .using_resolution(adapter.limits()), }, None, ) .await .expect("Failed to create device"); let swapchain_capabilities = surface.get_capabilities(&adapter); let swapchain_format = swapchain_capabilities.formats[0]; let mut config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, format: swapchain_format, width: size.width, height: size.height, present_mode: wgpu::PresentMode::Fifo, alpha_mode: swapchain_capabilities.alpha_modes[0], view_formats: vec![], }; surface.configure(&device, &config); // Create the context let context = Context::new(device, queue); // Load the shaders from disk let shader = Shader::new(include_wgsl!("shader.wgsl"), &context); let render_pipeline = RenderPipelineBuilder::with_vertex(&shader.entry_point("vs_main"), []) .fragment(&shader.entry_point("fs_main"), [Some(Default::default())]) .build(); event_loop.run(move |event, _, control_flow| { // Have the closure take ownership of the resources. // `event_loop.run` never returns, therefore we must do this to ensure // the resources are properly cleaned up. let _ = (&instance, &adapter, &shader); *control_flow = ControlFlow::Wait; match event { Event::WindowEvent { event: WindowEvent::Resized(size), .. } => { // Reconfigure the surface with the new size config.width = size.width; config.height = size.height; surface.configure(context.device(), &config); // On macos the window needs to be redrawn manually after resizing window.request_redraw(); } Event::RedrawRequested(_) => { let surface_texture = surface .get_current_texture() .expect("Failed to acquire next swap chain texture"); let target = RenderTexture::from_surface_texture(&surface_texture); { let mut frame = CommandEncoder::new(None, &context); { let mut rpass = frame.render_pass( None, vec![ColorAttachment { target, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color::GREEN), store: true, }, }], None, None, ); rpass.draw(DrawCall { bind_groups: vec![], bind_group_offsets: vec![], pipeline: render_pipeline.clone(), vertices: vec![], indices: None, element_range: 0..3, instance_range: 0..1, rasteriser_state: Default::default(), }); } } surface_texture.present(); } Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => *control_flow = ControlFlow::Exit, _ => {} } }); } fn main() { let event_loop = EventLoop::new(); let window = winit::window::Window::new(&event_loop).unwrap(); #[cfg(not(target_arch = "wasm32"))] { env_logger::init(); // Temporarily avoid srgb formats for the swapchain on the web pollster::block_on(run(event_loop, window)); } #[cfg(target_arch = "wasm32")] { std::panic::set_hook(Box::new(console_error_panic_hook::hook)); console_log::init().expect("could not initialize logger"); use winit::platform::web::WindowExtWebSys; // On wasm, append the canvas to the document body web_sys::window() .and_then(|win| win.document()) .and_then(|doc| doc.body()) .and_then(|body| { body.append_child(&web_sys::Element::from(window.canvas())) .ok() }) .expect("couldn't append canvas to document body"); wasm_bindgen_futures::spawn_local(run(event_loop, window)); } }