use super::super::{AaMode, Bound, Consts, GlobalsLayouts, Mesh, Tri}; use bytemuck::{Pod, Zeroable}; use vek::*; #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Locals { proj_mat_inv: [[f32; 4]; 4], view_mat_inv: [[f32; 4]; 4], } impl Default for Locals { fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) } } impl Locals { pub fn new(proj_mat_inv: Mat4, view_mat_inv: Mat4) -> Self { Self { proj_mat_inv: proj_mat_inv.into_col_arrays(), view_mat_inv: view_mat_inv.into_col_arrays(), } } } /*#[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { pub pos: [f32; 2], } impl Vertex { fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { use std::mem; const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 1] = wgpu::vertex_attr_array![0 => Float2]; wgpu::VertexBufferDescriptor { stride: mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Vertex, attributes: &ATTRIBUTES, } } } pub fn create_mesh() -> Mesh { let mut mesh = Mesh::new(); #[rustfmt::skip] mesh.push_tri(Tri::new( Vertex { pos: [ 1.0, -1.0] }, Vertex { pos: [-1.0, 1.0] }, Vertex { pos: [-1.0, -1.0] }, )); #[rustfmt::skip] mesh.push_tri(Tri::new( Vertex { pos: [1.0, -1.0] }, Vertex { pos: [1.0, 1.0] }, Vertex { pos: [-1.0, 1.0] }, )); mesh }*/ pub struct BindGroup { pub(in super::super) bind_group: wgpu::BindGroup, } pub struct PostProcessLayout { pub layout: wgpu::BindGroupLayout, } impl PostProcessLayout { pub fn new(device: &wgpu::Device) -> Self { Self { layout: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, entries: &[ // src color wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { component_type: wgpu::TextureComponentType::Float, dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { comparison: false }, count: None, }, // src depth wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { component_type: wgpu::TextureComponentType::Float, dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 3, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { comparison: false }, count: None, }, // Locals wgpu::BindGroupLayoutEntry { binding: 4, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::UniformBuffer { dynamic: false, min_binding_size: None, }, count: None, }, ], }), } } pub fn bind( &self, device: &wgpu::Device, src_color: &wgpu::TextureView, src_depth: &wgpu::TextureView, sampler: &wgpu::Sampler, locals: &Consts, ) -> BindGroup { let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: None, layout: &self.layout, entries: &[ wgpu::BindGroupEntry { binding: 0, resource: wgpu::BindingResource::TextureView(src_color), }, wgpu::BindGroupEntry { binding: 1, resource: wgpu::BindingResource::Sampler(sampler), }, wgpu::BindGroupEntry { binding: 2, resource: wgpu::BindingResource::TextureView(src_depth), }, wgpu::BindGroupEntry { binding: 3, resource: wgpu::BindingResource::Sampler(sampler), }, wgpu::BindGroupEntry { binding: 4, resource: locals.buf().as_entire_binding(), }, ], }); BindGroup { bind_group } } } pub struct PostProcessPipeline { pub pipeline: wgpu::RenderPipeline, } impl PostProcessPipeline { pub fn new( device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, sc_desc: &wgpu::SwapChainDescriptor, global_layout: &GlobalsLayouts, layout: &PostProcessLayout, aa_mode: AaMode, ) -> Self { common::span!(_guard, "PostProcessPipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Post process pipeline layout"), push_constant_ranges: &[], bind_group_layouts: &[&global_layout.globals, &layout.layout], }); let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, // TODO: Ensure sampling in the shader is exactly between the 4 texels AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, }; let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Post process pipeline"), layout: Some(&render_pipeline_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::Ccw, cull_mode: wgpu::CullMode::Back, polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: false, depth_bias: 0, depth_bias_slope_scale: 0.0, depth_bias_clamp: 0.0, }), primitive_topology: wgpu::PrimitiveTopology::TriangleList, 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: Some(wgpu::DepthStencilStateDescriptor { format: wgpu::TextureFormat::Depth24Plus, depth_write_enabled: false, depth_compare: wgpu::CompareFunction::Always, stencil: wgpu::StencilStateDescriptor { front: wgpu::StencilStateFaceDescriptor::IGNORE, back: wgpu::StencilStateFaceDescriptor::IGNORE, read_mask: !0, write_mask: !0, }, }), vertex_state: wgpu::VertexStateDescriptor { index_format: wgpu::IndexFormat::Uint16, vertex_buffers: &[/*Vertex::desc()*/], }, sample_count: samples, sample_mask: !0, alpha_to_coverage_enabled: false, }); Self { pipeline: render_pipeline, } } }