From 2bda1508f166e453290e2030f350c61ee907e288 Mon Sep 17 00:00:00 2001 From: Wumpf Date: Tue, 16 Mar 2021 03:33:44 +0100 Subject: [PATCH] [rs] Added example for conservative rasterization (#791) * Example for conservative rasterization * Update to wgpu-core/types 717c2d73e725c064a3c4696d6d7bdb428c9500b6 * conservative-raster example: fix wglsl const & readme * conservative raster example: optional lines, no more interaction --- wgpu/Cargo.toml | 6 +- wgpu/examples/README.md | 69 ++-- wgpu/examples/conservative-raster/README.md | 20 ++ wgpu/examples/conservative-raster/main.rs | 316 ++++++++++++++++++ .../conservative-raster/screenshot.png | Bin 0 -> 19106 bytes .../triangle_and_lines.wgsl | 22 ++ .../examples/conservative-raster/upscale.wgsl | 24 ++ 7 files changed, 420 insertions(+), 37 deletions(-) create mode 100644 wgpu/examples/conservative-raster/README.md create mode 100644 wgpu/examples/conservative-raster/main.rs create mode 100644 wgpu/examples/conservative-raster/screenshot.png create mode 100644 wgpu/examples/conservative-raster/triangle_and_lines.wgsl create mode 100644 wgpu/examples/conservative-raster/upscale.wgsl diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index 3de4f3289a..5ecb007aaf 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -26,20 +26,20 @@ webgl = ["wgc"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "5e15980bb53d2a5c24546dab640dcc72d211bd36" +rev = "717c2d73e725c064a3c4696d6d7bdb428c9500b6" features = ["raw-window-handle", "cross"] [target.'cfg(target_arch = "wasm32")'.dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "5e15980bb53d2a5c24546dab640dcc72d211bd36" +rev = "717c2d73e725c064a3c4696d6d7bdb428c9500b6" features = ["raw-window-handle", "cross"] optional = true [dependencies.wgt] package = "wgpu-types" git = "https://github.com/gfx-rs/wgpu" -rev = "5e15980bb53d2a5c24546dab640dcc72d211bd36" +rev = "717c2d73e725c064a3c4696d6d7bdb428c9500b6" [dependencies] arrayvec = "0.5" diff --git a/wgpu/examples/README.md b/wgpu/examples/README.md index e1740072e6..f2e178edbd 100644 --- a/wgpu/examples/README.md +++ b/wgpu/examples/README.md @@ -10,40 +10,41 @@ Notably, `capture` example shows rendering without a surface/window. It reads ba All framework-based examples render to the window. ## Feature matrix -| Feature | boids | cube | mipmap | msaa-line | shadow | skybox | texture-arrays | water | -| ---------------------- | ------ | ------ | ------ | --------- | ------ | ------ | -------------- | ------ | -| WGSL shaders | :star: | :star: | :star: | :star: | :star: | :star: | | | -| vertex attributes | :star: | :star: | | :star: | :star: | :star: | :star: | :star: | -| instancing | :star: | | | | | | | | -| lines and points | | | | :star: | | | | | -| dynamic buffer offsets | | | | | :star: | | | | -| implicit layout | | | :star: | | | | | | -| sampled color textures | :star: | :star: | :star: | | | :star: | :star: | :star: | -| storage textures | :star: | | | | | | | | -| binding array | | | | | | | :star: | | -| comparison samplers | | | | | :star: | | | | -| subresource views | | | :star: | | :star: | | | | -| cubemaps | | | | | | :star: | | | -| multisampling | | | | :star: | | | | | -| off-screen rendering | | | | | :star: | | | :star: | -| stencil testing | | | | | | | | | -| depth testing | | | | | :star: | :star: | | :star: | -| depth biasing | | | | | :star: | | | | -| read-only depth | | | | | | | | :star: | -| blending | | :star: | | | | | | :star: | -| render bundles | | | | :star: | | | | :star: | -| compute passes | :star: | | | | | | | | -| *optional extensions* | | | | | | | :star: | | -| - binding indexing | | | | | | | :star: | | -| - push constants | | | | | | | :star: | | -| - depth clamping | | | | | :star: | | | | -| - compressed textures | | | | | | :star: | | | -| - polygon mode | | :star: | | | | | | | -| - queries | | | :star: | | | | | | -| *integrations* | | | | | | | | | -| - staging belt | | | | | | | | | -| - typed arena | | | | | | | | | -| - obj loading | | | | | | :star: | | | +| Feature | boids | cube | mipmap | msaa-line | shadow | skybox | texture-arrays | water | conservative-raster | +| ---------------------------- | ------ | ------ | ------ | --------- | ------ | ------ | -------------- | ------ | ------------------- | +| WGSL shaders | :star: | :star: | :star: | :star: | :star: | :star: | | | :star: | +| vertex attributes | :star: | :star: | | :star: | :star: | :star: | :star: | :star: | | +| instancing | :star: | | | | | | | | | +| lines and points | | | | :star: | | | | | :star: | +| dynamic buffer offsets | | | | | :star: | | | | | +| implicit layout | | | :star: | | | | | | | +| sampled color textures | :star: | :star: | :star: | | | :star: | :star: | :star: | :star: | +| storage textures | :star: | | | | | | | | | +| binding array | | | | | | | :star: | | | +| comparison samplers | | | | | :star: | | | | | +| subresource views | | | :star: | | :star: | | | | | +| cubemaps | | | | | | :star: | | | | +| multisampling | | | | :star: | | | | | | +| off-screen rendering | | | | | :star: | | | :star: | :star: | +| stencil testing | | | | | | | | | | +| depth testing | | | | | :star: | :star: | | :star: | | +| depth biasing | | | | | :star: | | | | | +| read-only depth | | | | | | | | :star: | | +| blending | | :star: | | | | | | :star: | | +| render bundles | | | | :star: | | | | :star: | | +| compute passes | :star: | | | | | | | | | +| *optional extensions* | | | | | | | :star: | | | +| - binding indexing | | | | | | | :star: | | | +| - push constants | | | | | | | :star: | | | +| - depth clamping | | | | | :star: | | | | | +| - compressed textures | | | | | | :star: | | | | +| - polygon mode | | :star: | | | | | | | | +| - queries | | | :star: | | | | | | | +| - conservative rasterization | | | | | | | | | :star: | +| *integrations* | | | | | | | | | | +| - staging belt | | | | | | | | | | +| - typed arena | | | | | | | | | | +| - obj loading | | | | | | :star: | | | | ## Hacking diff --git a/wgpu/examples/conservative-raster/README.md b/wgpu/examples/conservative-raster/README.md new file mode 100644 index 0000000000..bd157319b5 --- /dev/null +++ b/wgpu/examples/conservative-raster/README.md @@ -0,0 +1,20 @@ +# conservative-raster + +This example shows how to render with conservative rasterization (native extension with limited support). + +When enabled, any pixel touched by a triangle primitive is rasterized. +This is useful for various advanced techniques, most prominently for implementing realtime voxelization. + +The demonstration here is implemented by rendering a triangle to a low-resolution target and then upscaling it with nearest-neighbor filtering. +The outlines of the triangle are then rendered in the original solution, using the same vertex shader as the triangle. +Pixels only drawn with conservative rasterization enabled are depicted red. + +## To Run + +``` +cargo run --example conservative-raster +``` + +## Screenshots + +![Conservative-raster window](./screenshot.png) diff --git a/wgpu/examples/conservative-raster/main.rs b/wgpu/examples/conservative-raster/main.rs new file mode 100644 index 0000000000..e379520fab --- /dev/null +++ b/wgpu/examples/conservative-raster/main.rs @@ -0,0 +1,316 @@ +#[path = "../framework.rs"] +mod framework; + +use std::borrow::Cow; + +const RENDER_TARGET_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba8UnormSrgb; + +struct Example { + low_res_target: wgpu::TextureView, + bind_group_upscale: wgpu::BindGroup, + + pipeline_triangle_conservative: wgpu::RenderPipeline, + pipeline_triangle_regular: wgpu::RenderPipeline, + pipeline_upscale: wgpu::RenderPipeline, + pipeline_lines: Option, + bind_group_layout_upscale: wgpu::BindGroupLayout, +} + +impl Example { + fn create_low_res_target( + sc_desc: &wgpu::SwapChainDescriptor, + device: &wgpu::Device, + bind_group_layout_upscale: &wgpu::BindGroupLayout, + ) -> (wgpu::TextureView, wgpu::BindGroup) { + let texture_view = device + .create_texture(&wgpu::TextureDescriptor { + label: Some("Low Resolution Target"), + size: wgpu::Extent3d { + width: sc_desc.width / 16, + height: sc_desc.width / 16, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: RENDER_TARGET_FORMAT, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, + }) + .create_view(&Default::default()); + + let sampler = device.create_sampler(&wgpu::SamplerDescriptor { + label: Some("Nearest Neighbor Sampler"), + mag_filter: wgpu::FilterMode::Nearest, + min_filter: wgpu::FilterMode::Nearest, + ..Default::default() + }); + + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("upscale bind group"), + layout: &bind_group_layout_upscale, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&texture_view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&sampler), + }, + ], + }); + + (texture_view, bind_group) + } +} + +impl framework::Example for Example { + fn required_features() -> wgpu::Features { + wgpu::Features::CONSERVATIVE_RASTERIZATION + } + fn optional_features() -> wgpu::Features { + wgpu::Features::NON_FILL_POLYGON_MODE + } + fn init( + sc_desc: &wgpu::SwapChainDescriptor, + adapter: &wgpu::Adapter, + device: &wgpu::Device, + _queue: &wgpu::Queue, + ) -> Self { + let pipeline_layout_empty = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: None, + bind_group_layouts: &[], + push_constant_ranges: &[], + }); + + let shader_triangle_and_lines = + device.create_shader_module(&wgpu::ShaderModuleDescriptor { + label: None, + source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!( + "triangle_and_lines.wgsl" + ))), + flags: wgpu::ShaderFlags::all(), + }); + + let pipeline_triangle_conservative = + device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Conservative Rasterization"), + layout: Some(&pipeline_layout_empty), + vertex: wgpu::VertexState { + module: &shader_triangle_and_lines, + entry_point: "vs_main", + buffers: &[], + }, + fragment: Some(wgpu::FragmentState { + module: &shader_triangle_and_lines, + entry_point: "fs_main_red", + targets: &[RENDER_TARGET_FORMAT.into()], + }), + primitive: wgpu::PrimitiveState { + conservative: true, + ..Default::default() + }, + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + }); + + let pipeline_triangle_regular = + device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Regular Rasterization"), + layout: Some(&pipeline_layout_empty), + vertex: wgpu::VertexState { + module: &shader_triangle_and_lines, + entry_point: "vs_main", + buffers: &[], + }, + fragment: Some(wgpu::FragmentState { + module: &shader_triangle_and_lines, + entry_point: "fs_main_blue", + targets: &[RENDER_TARGET_FORMAT.into()], + }), + primitive: wgpu::PrimitiveState::default(), + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + }); + + let pipeline_lines = if adapter + .features() + .contains(wgpu::Features::NON_FILL_POLYGON_MODE) + { + Some( + device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Lines"), + layout: Some(&pipeline_layout_empty), + vertex: wgpu::VertexState { + module: &shader_triangle_and_lines, + entry_point: "vs_main", + buffers: &[], + }, + fragment: Some(wgpu::FragmentState { + module: &shader_triangle_and_lines, + entry_point: "fs_main_white", + targets: &[sc_desc.format.into()], + }), + primitive: wgpu::PrimitiveState { + polygon_mode: wgpu::PolygonMode::Line, + topology: wgpu::PrimitiveTopology::LineStrip, + ..Default::default() + }, + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + }), + ) + } else { + None + }; + + let (pipeline_upscale, bind_group_layout_upscale) = { + let bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("upscale bindgroup"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: false }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { + filtering: false, + comparison: false, + }, + count: None, + }, + ], + }); + + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: None, + bind_group_layouts: &[&bind_group_layout], + push_constant_ranges: &[], + }); + let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor { + label: None, + source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("upscale.wgsl"))), + flags: wgpu::ShaderFlags::all(), + }); + ( + device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Upscale"), + 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: &[sc_desc.format.into()], + }), + primitive: wgpu::PrimitiveState::default(), + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + }), + bind_group_layout, + ) + }; + + let (low_res_target, bind_group_upscale) = + Self::create_low_res_target(sc_desc, device, &bind_group_layout_upscale); + + Self { + low_res_target, + bind_group_upscale, + + pipeline_triangle_conservative, + pipeline_triangle_regular, + pipeline_upscale, + pipeline_lines, + bind_group_layout_upscale, + } + } + + fn resize( + &mut self, + sc_desc: &wgpu::SwapChainDescriptor, + device: &wgpu::Device, + _queue: &wgpu::Queue, + ) { + let (low_res_target, bind_group_upscale) = + Self::create_low_res_target(sc_desc, device, &self.bind_group_layout_upscale); + self.low_res_target = low_res_target; + self.bind_group_upscale = bind_group_upscale; + } + + fn update(&mut self, _event: winit::event::WindowEvent) {} + + fn render( + &mut self, + frame: &wgpu::SwapChainTexture, + device: &wgpu::Device, + queue: &wgpu::Queue, + _spawner: &framework::Spawner, + ) { + let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("primary"), + }); + + { + let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("low resolution"), + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &self.low_res_target, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), + store: true, + }, + }], + depth_stencil_attachment: None, + }); + + rpass.set_pipeline(&self.pipeline_triangle_conservative); + rpass.draw(0..3, 0..1); + rpass.set_pipeline(&self.pipeline_triangle_regular); + rpass.draw(0..3, 0..1); + } + { + let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("full resolution"), + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &frame.view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), + store: true, + }, + }], + depth_stencil_attachment: None, + }); + + rpass.set_pipeline(&self.pipeline_upscale); + rpass.set_bind_group(0, &self.bind_group_upscale, &[]); + rpass.draw(0..3, 0..1); + + if let Some(pipeline_lines) = &self.pipeline_lines { + rpass.set_pipeline(pipeline_lines); + rpass.draw(0..4, 0..1); + } + } + + queue.submit(Some(encoder.finish())); + } +} + +fn main() { + framework::run::("conservative-raster"); +} diff --git a/wgpu/examples/conservative-raster/screenshot.png b/wgpu/examples/conservative-raster/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..e227e10e659f795267464910db71ba73c0cacd9b GIT binary patch literal 19106 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 [[builtin(position)]] vec4 { + const i: i32 = i32(vertex_index % 3u); + const x: f32 = f32(i - 1) * 0.75; + const y: f32 = f32((i & 1) * 2 - 1) * 0.75 + x * 0.2 + 0.1; + return vec4(x, y, 0.0, 1.0); +} + +[[stage(fragment)]] +fn fs_main_red() -> [[location(0)]] vec4 { + return vec4(1.0, 0.0, 0.0, 1.0); +} + +[[stage(fragment)]] +fn fs_main_blue() -> [[location(0)]] vec4 { + return vec4(0.13, 0.31, 0.85, 1.0); // cornflower blue in linear space +} + +[[stage(fragment)]] +fn fs_main_white() -> [[location(0)]] vec4 { + return vec4(1.0, 1.0, 1.0, 1.0); +} \ No newline at end of file diff --git a/wgpu/examples/conservative-raster/upscale.wgsl b/wgpu/examples/conservative-raster/upscale.wgsl new file mode 100644 index 0000000000..ff1c00ebaa --- /dev/null +++ b/wgpu/examples/conservative-raster/upscale.wgsl @@ -0,0 +1,24 @@ +struct VertexOutput { + [[builtin(position)]] position: vec4; + [[location(0)]] tex_coords: vec2; +}; + +[[stage(vertex)]] +fn vs_main([[builtin(vertex_index)]] vertex_index: u32) -> VertexOutput { + const x: f32 = f32(i32(vertex_index & 1) << 2) - 1.0; + const y: f32 = f32(i32(vertex_index & 2) << 1) - 1.0; + var output: VertexOutput; + output.position = vec4(x, -y, 0.0, 1.0); + output.tex_coords = vec2(x + 1.0, y + 1.0) * 0.5; + return output; +} + +[[group(0), binding(0)]] +var r_color: texture_2d; +[[group(0), binding(1)]] +var r_sampler: sampler; + +[[stage(fragment)]] +fn fs_main(in: VertexOutput) -> [[location(0)]] vec4 { + return textureSample(r_color, r_sampler, in.tex_coords); +} \ No newline at end of file