From 051be88729814e98c370b5e3b521f7f21806df8b Mon Sep 17 00:00:00 2001 From: Rukai Date: Tue, 18 Jun 2019 14:25:45 +1000 Subject: [PATCH] [rs] Add MSAA + LineList example --- wgpu/examples/msaa-linelist/main.rs | 212 ++++++++++++++++++++++++ wgpu/examples/msaa-linelist/shader.frag | 8 + wgpu/examples/msaa-linelist/shader.vert | 10 ++ 3 files changed, 230 insertions(+) create mode 100644 wgpu/examples/msaa-linelist/main.rs create mode 100644 wgpu/examples/msaa-linelist/shader.frag create mode 100644 wgpu/examples/msaa-linelist/shader.vert diff --git a/wgpu/examples/msaa-linelist/main.rs b/wgpu/examples/msaa-linelist/main.rs new file mode 100644 index 000000000..e55d0770b --- /dev/null +++ b/wgpu/examples/msaa-linelist/main.rs @@ -0,0 +1,212 @@ +//! The parts of this example enabling MSAA are: +//! * The render pipeline is created with a sample_count > 1. +//! * A new texture with a sample_count > 1 is created and set as the color_attachment instead of the swapchain. +//! * The swapchain is now specified as a resolve_target. +//! +//! The parts of this example enabling LineList are: +//! * Set the primitive_topology to PrimitiveTopology::LineList. +//! * Vertices and Indices describe the two points that make up a line. + +#[path = "../framework.rs"] +mod framework; + +#[derive(Clone, Copy)] +struct Vertex { + _pos: [f32; 2], + _color: [f32; 4], +} + +struct Example { + vs_module: wgpu::ShaderModule, + fs_module: wgpu::ShaderModule, + pipeline_layout: wgpu::PipelineLayout, + pipeline: wgpu::RenderPipeline, + multisampled_framebuffer: wgpu::TextureView, + vertex_buffer: wgpu::Buffer, + vertex_count: u32, + rebuild_pipeline: bool, + sample_count: u32, + sc_desc: wgpu::SwapChainDescriptor, +} + +impl Example { + fn create_pipeline(device: &wgpu::Device, sc_desc: &wgpu::SwapChainDescriptor, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, pipeline_layout: &wgpu::PipelineLayout, sample_count: u32) -> wgpu::RenderPipeline { + println!("sample_count: {}", sample_count); + device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + layout: &pipeline_layout, + vertex_stage: wgpu::PipelineStageDescriptor { + module: vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::PipelineStageDescriptor { + module: fs_module, + entry_point: "main", + }), + rasterization_state: wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::None, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }, + primitive_topology: wgpu::PrimitiveTopology::LineList, + color_states: &[wgpu::ColorStateDescriptor { + format: sc_desc.format, + color_blend: wgpu::BlendDescriptor::REPLACE, + alpha_blend: wgpu::BlendDescriptor::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], + depth_stencil_state: None, + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[wgpu::VertexBufferDescriptor { + stride: std::mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::InputStepMode::Vertex, + attributes: &[ + wgpu::VertexAttributeDescriptor { + format: wgpu::VertexFormat::Float2, + offset: 0, + shader_location: 0, + }, + wgpu::VertexAttributeDescriptor { + format: wgpu::VertexFormat::Float4, + offset: 2 * 4, + shader_location: 1, + }, + ], + }], + sample_count, + }) + } + + fn create_multisampled_framebuffer(device: &wgpu::Device, sc_desc: &wgpu::SwapChainDescriptor, sample_count: u32) -> wgpu::TextureView { + let multisampled_texture_extent = wgpu::Extent3d { + width: sc_desc.width, + height: sc_desc.height, + depth: 1, + }; + let multisampled_frame_descriptor = &wgpu::TextureDescriptor { + size: multisampled_texture_extent, + array_layer_count: 1, + mip_level_count: 1, + sample_count: sample_count, + dimension: wgpu::TextureDimension::D2, + format: sc_desc.format, + usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, + }; + + device.create_texture(multisampled_frame_descriptor).create_default_view() + } +} + +impl framework::Example for Example { + fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device) -> Self { + println!("Press left/right arrow keys to change sample_count."); + let sample_count = 2; + + let vs_bytes = framework::load_glsl(include_str!("shader.vert"), framework::ShaderStage::Vertex); + let fs_bytes = framework::load_glsl(include_str!("shader.frag"), framework::ShaderStage::Fragment); + let vs_module = device.create_shader_module(&vs_bytes); + let fs_module = device.create_shader_module(&fs_bytes); + + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + bind_group_layouts: &[], + }); + + let pipeline = Example::create_pipeline(device, &sc_desc, &vs_module, &fs_module, &pipeline_layout, sample_count); + let multisampled_framebuffer = Example::create_multisampled_framebuffer(device, sc_desc, sample_count); + + let mut vertex_data = vec!(); + + let max = 50; + for i in 0..max { + let percent = i as f32 / max as f32; + let (sin, cos) = (percent * 2.0 * std::f32::consts::PI).sin_cos(); + vertex_data.push(Vertex { + _pos: [0.0, 0.0], + _color: [1.0, -sin, cos, 1.0], + }); + vertex_data.push(Vertex { + _pos: [1.0 * cos, 1.0 * sin], + _color: [sin, -cos, 1.0, 1.0], + }); + } + + let vertex_buffer = device + .create_buffer_mapped(vertex_data.len(), wgpu::BufferUsage::VERTEX) + .fill_from_slice(&vertex_data); + let vertex_count = vertex_data.len() as u32; + + Example { + vs_module, + fs_module, + pipeline_layout, + pipeline, + multisampled_framebuffer, + vertex_buffer, + vertex_count, + rebuild_pipeline: false, + sample_count, + sc_desc: sc_desc.clone(), + } + } + + fn update(&mut self, event: wgpu::winit::WindowEvent) { + match event { + wgpu::winit::WindowEvent::KeyboardInput { input, .. } => { + if let wgpu::winit::ElementState::Pressed = input.state { + match input.virtual_keycode { + Some(wgpu::winit::VirtualKeyCode::Left) => { + if self.sample_count >= 2 { + self.sample_count = self.sample_count >> 1; + self.rebuild_pipeline = true; + } + } + Some(wgpu::winit::VirtualKeyCode::Right) => { + if self.sample_count <= 16 { + self.sample_count = self.sample_count << 1; + self.rebuild_pipeline = true; + } + } + _ => { } + } + } + } + _ => { } + } + } + + fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device) { + self.sc_desc = sc_desc.clone(); + self.multisampled_framebuffer = Example::create_multisampled_framebuffer(device, sc_desc, self.sample_count); + } + + fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &mut wgpu::Device) { + if self.rebuild_pipeline { + self.pipeline = Example::create_pipeline(device, &self.sc_desc, &self.vs_module, &self.fs_module, &self.pipeline_layout, self.sample_count); + self.rebuild_pipeline = false; + } + + let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); + { + let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &self.multisampled_framebuffer, + resolve_target: Some(&frame.view), + load_op: wgpu::LoadOp::Clear, + store_op: wgpu::StoreOp::Store, + clear_color: wgpu::Color::BLACK, + }], + depth_stencil_attachment: None, + }); + rpass.set_pipeline(&self.pipeline); + rpass.set_vertex_buffers(&[(&self.vertex_buffer, 0)]); + rpass.draw(0..self.vertex_count, 0..1); + } + + device.get_queue().submit(&[encoder.finish()]); + } +} + +fn main() { + framework::run::("MSAA and LineList"); +} diff --git a/wgpu/examples/msaa-linelist/shader.frag b/wgpu/examples/msaa-linelist/shader.frag new file mode 100644 index 000000000..1bb727606 --- /dev/null +++ b/wgpu/examples/msaa-linelist/shader.frag @@ -0,0 +1,8 @@ +#version 450 + +layout(location = 0) in vec4 v_Color; +layout(location = 0) out vec4 f_Color; + +void main() { + f_Color = v_Color; +} diff --git a/wgpu/examples/msaa-linelist/shader.vert b/wgpu/examples/msaa-linelist/shader.vert new file mode 100644 index 000000000..ccff02f1b --- /dev/null +++ b/wgpu/examples/msaa-linelist/shader.vert @@ -0,0 +1,10 @@ +#version 450 + +layout(location = 0) in vec2 a_Pos; +layout(location = 1) in vec4 a_Color; +layout(location = 0) out vec4 f_Color; + +void main() { + gl_Position = vec4(a_Pos, 0.0, 1.0); + f_Color = a_Color; +}