Created
June 28, 2021 18:59
-
-
Save caelunshun/b0a52181361799d358a849b30fe2d30b to your computer and use it in GitHub Desktop.
wgpu hello-triangle with GLFW
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::borrow::Cow; | |
use glfw::WindowEvent; | |
async fn run() { | |
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap(); | |
let (window, events) = glfw | |
.create_window( | |
1920 / 2, | |
1080 / 2, | |
"wgpu example", | |
glfw::WindowMode::Windowed, | |
) | |
.unwrap(); | |
let (width, height) = window.get_size(); | |
let instance = wgpu::Instance::new(wgpu::BackendBit::all()); | |
let surface = unsafe { instance.create_surface(&window) }; | |
let adapter = instance | |
.request_adapter(&wgpu::RequestAdapterOptions { | |
power_preference: wgpu::PowerPreference::HighPerformance, | |
// 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(), | |
limits: wgpu::Limits::default(), | |
}, | |
None, | |
) | |
.await | |
.expect("Failed to create device"); | |
// Load the shaders from disk | |
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor { | |
label: None, | |
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))), | |
}); | |
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { | |
label: None, | |
bind_group_layouts: &[], | |
push_constant_ranges: &[], | |
}); | |
let swapchain_format = adapter.get_swap_chain_preferred_format(&surface).unwrap(); | |
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { | |
label: None, | |
layout: Some(&pipeline_layout), | |
vertex: wgpu::VertexState { | |
module: &shader, | |
entry_point: "vs_main", | |
buffers: &[], | |
}, | |
fragment: Some(wgpu::FragmentState { | |
module: &shader, | |
entry_point: "fs_main", | |
targets: &[swapchain_format.into()], | |
}), | |
primitive: wgpu::PrimitiveState::default(), | |
depth_stencil: None, | |
multisample: wgpu::MultisampleState::default(), | |
}); | |
let mut sc_desc = wgpu::SwapChainDescriptor { | |
usage: wgpu::TextureUsage::RENDER_ATTACHMENT, | |
format: swapchain_format, | |
width: width as u32, | |
height: height as u32, | |
present_mode: wgpu::PresentMode::Fifo, | |
}; | |
let mut swap_chain = device.create_swap_chain(&surface, &sc_desc); | |
while !window.should_close() { | |
glfw.poll_events(); | |
for (_, event) in glfw::flush_messages(&events) { | |
match event { | |
WindowEvent::Size(new_width, new_height) => { | |
// Recreate the swap chain with the new size | |
sc_desc.width = new_width as u32; | |
sc_desc.height = new_height as u32; | |
swap_chain = device.create_swap_chain(&surface, &sc_desc); | |
} | |
_ => {} | |
} | |
} | |
let frame = swap_chain | |
.get_current_frame() | |
.expect("Failed to acquire next swap chain texture") | |
.output; | |
let mut encoder = | |
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); | |
{ | |
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { | |
label: None, | |
color_attachments: &[wgpu::RenderPassColorAttachment { | |
view: &frame.view, | |
resolve_target: None, | |
ops: wgpu::Operations { | |
load: wgpu::LoadOp::Clear(wgpu::Color::GREEN), | |
store: true, | |
}, | |
}], | |
depth_stencil_attachment: None, | |
}); | |
rpass.set_pipeline(&render_pipeline); | |
rpass.draw(0..3, 0..1); | |
} | |
queue.submit(Some(encoder.finish())); | |
} | |
} | |
fn main() { | |
#[cfg(not(target_arch = "wasm32"))] | |
{ | |
env_logger::init(); | |
// Temporarily avoid srgb formats for the swapchain on the web | |
pollster::block_on(run()); | |
} | |
#[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)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment