diff options
Diffstat (limited to 'wgpu/src/triangle')
| -rw-r--r-- | wgpu/src/triangle/msaa.rs | 255 | 
1 files changed, 255 insertions, 0 deletions
diff --git a/wgpu/src/triangle/msaa.rs b/wgpu/src/triangle/msaa.rs new file mode 100644 index 00000000..93fbe49b --- /dev/null +++ b/wgpu/src/triangle/msaa.rs @@ -0,0 +1,255 @@ +use crate::settings; + +#[derive(Debug)] +pub struct Blit { +    pipeline: wgpu::RenderPipeline, +    constants: wgpu::BindGroup, +    texture_layout: wgpu::BindGroupLayout, +    sample_count: u32, +    targets: Option<Targets>, +} + +impl Blit { +    pub fn new(device: &wgpu::Device, antialiasing: settings::MSAA) -> Blit { +        let sampler = device.create_sampler(&wgpu::SamplerDescriptor { +            address_mode_u: wgpu::AddressMode::ClampToEdge, +            address_mode_v: wgpu::AddressMode::ClampToEdge, +            address_mode_w: wgpu::AddressMode::ClampToEdge, +            mag_filter: wgpu::FilterMode::Linear, +            min_filter: wgpu::FilterMode::Linear, +            mipmap_filter: wgpu::FilterMode::Linear, +            lod_min_clamp: -100.0, +            lod_max_clamp: 100.0, +            compare_function: wgpu::CompareFunction::Always, +        }); + +        let constant_layout = +            device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { +                bindings: &[wgpu::BindGroupLayoutBinding { +                    binding: 0, +                    visibility: wgpu::ShaderStage::FRAGMENT, +                    ty: wgpu::BindingType::Sampler, +                }], +            }); + +        let constant_bind_group = +            device.create_bind_group(&wgpu::BindGroupDescriptor { +                layout: &constant_layout, +                bindings: &[wgpu::Binding { +                    binding: 0, +                    resource: wgpu::BindingResource::Sampler(&sampler), +                }], +            }); + +        let texture_layout = +            device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { +                bindings: &[wgpu::BindGroupLayoutBinding { +                    binding: 0, +                    visibility: wgpu::ShaderStage::FRAGMENT, +                    ty: wgpu::BindingType::SampledTexture { +                        multisampled: false, +                        dimension: wgpu::TextureViewDimension::D2, +                    }, +                }], +            }); + +        let layout = +            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { +                bind_group_layouts: &[&constant_layout, &texture_layout], +            }); + +        let vs = include_bytes!("../shader/blit.vert.spv"); +        let vs_module = device.create_shader_module( +            &wgpu::read_spirv(std::io::Cursor::new(&vs[..])) +                .expect("Read blit vertex shader as SPIR-V"), +        ); + +        let fs = include_bytes!("../shader/blit.frag.spv"); +        let fs_module = device.create_shader_module( +            &wgpu::read_spirv(std::io::Cursor::new(&fs[..])) +                .expect("Read blit fragment shader as SPIR-V"), +        ); + +        let pipeline = +            device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { +                layout: &layout, +                vertex_stage: wgpu::ProgrammableStageDescriptor { +                    module: &vs_module, +                    entry_point: "main", +                }, +                fragment_stage: Some(wgpu::ProgrammableStageDescriptor { +                    module: &fs_module, +                    entry_point: "main", +                }), +                rasterization_state: Some(wgpu::RasterizationStateDescriptor { +                    front_face: wgpu::FrontFace::Cw, +                    cull_mode: wgpu::CullMode::None, +                    depth_bias: 0, +                    depth_bias_slope_scale: 0.0, +                    depth_bias_clamp: 0.0, +                }), +                primitive_topology: wgpu::PrimitiveTopology::TriangleList, +                color_states: &[wgpu::ColorStateDescriptor { +                    format: wgpu::TextureFormat::Bgra8UnormSrgb, +                    color_blend: wgpu::BlendDescriptor { +                        src_factor: wgpu::BlendFactor::SrcAlpha, +                        dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, +                        operation: wgpu::BlendOperation::Add, +                    }, +                    alpha_blend: wgpu::BlendDescriptor { +                        src_factor: wgpu::BlendFactor::One, +                        dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, +                        operation: wgpu::BlendOperation::Add, +                    }, +                    write_mask: wgpu::ColorWrite::ALL, +                }], +                depth_stencil_state: None, +                index_format: wgpu::IndexFormat::Uint16, +                vertex_buffers: &[], +                sample_count: 1, +                sample_mask: !0, +                alpha_to_coverage_enabled: false, +            }); + +        Blit { +            pipeline, +            constants: constant_bind_group, +            texture_layout: texture_layout, +            sample_count: antialiasing.sample_count(), +            targets: None, +        } +    } + +    pub fn targets( +        &mut self, +        device: &wgpu::Device, +        width: u32, +        height: u32, +    ) -> (&wgpu::TextureView, &wgpu::TextureView) { +        match &mut self.targets { +            None => { +                self.targets = Some(Targets::new( +                    &device, +                    &self.texture_layout, +                    self.sample_count, +                    width, +                    height, +                )); +            } +            Some(targets) => { +                if targets.width != width || targets.height != height { +                    self.targets = Some(Targets::new( +                        &device, +                        &self.texture_layout, +                        self.sample_count, +                        width, +                        height, +                    )); +                } +            } +        } + +        let targets = self.targets.as_ref().unwrap(); + +        (&targets.attachment, &targets.resolve) +    } + +    pub fn draw( +        &self, +        encoder: &mut wgpu::CommandEncoder, +        target: &wgpu::TextureView, +    ) { +        let mut render_pass = +            encoder.begin_render_pass(&wgpu::RenderPassDescriptor { +                color_attachments: &[ +                    wgpu::RenderPassColorAttachmentDescriptor { +                        attachment: target, +                        resolve_target: None, +                        load_op: wgpu::LoadOp::Load, +                        store_op: wgpu::StoreOp::Store, +                        clear_color: wgpu::Color { +                            r: 0.0, +                            g: 0.0, +                            b: 0.0, +                            a: 0.0, +                        }, +                    }, +                ], +                depth_stencil_attachment: None, +            }); + +        render_pass.set_pipeline(&self.pipeline); +        render_pass.set_bind_group(0, &self.constants, &[]); +        render_pass.set_bind_group( +            1, +            &self.targets.as_ref().unwrap().bind_group, +            &[], +        ); +        render_pass.draw(0..6, 0..1); +    } +} + +#[derive(Debug)] +struct Targets { +    attachment: wgpu::TextureView, +    resolve: wgpu::TextureView, +    bind_group: wgpu::BindGroup, +    width: u32, +    height: u32, +} + +impl Targets { +    pub fn new( +        device: &wgpu::Device, +        texture_layout: &wgpu::BindGroupLayout, +        sample_count: u32, +        width: u32, +        height: u32, +    ) -> Targets { +        let extent = wgpu::Extent3d { +            width, +            height, +            depth: 1, +        }; + +        let attachment = device.create_texture(&wgpu::TextureDescriptor { +            size: extent, +            array_layer_count: 1, +            mip_level_count: 1, +            sample_count, +            dimension: wgpu::TextureDimension::D2, +            format: wgpu::TextureFormat::Bgra8UnormSrgb, +            usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, +        }); + +        let resolve = device.create_texture(&wgpu::TextureDescriptor { +            size: extent, +            array_layer_count: 1, +            mip_level_count: 1, +            sample_count: 1, +            dimension: wgpu::TextureDimension::D2, +            format: wgpu::TextureFormat::Bgra8UnormSrgb, +            usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT +                | wgpu::TextureUsage::SAMPLED, +        }); + +        let attachment = attachment.create_default_view(); +        let resolve = resolve.create_default_view(); + +        let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { +            layout: texture_layout, +            bindings: &[wgpu::Binding { +                binding: 0, +                resource: wgpu::BindingResource::TextureView(&resolve), +            }], +        }); + +        Targets { +            attachment, +            resolve, +            bind_group, +            width, +            height, +        } +    } +}  | 
