use super::super::{AaMode, Bound, Consts, GlobalsLayouts, Vertex as VertexTrait}; use bytemuck::{Pod, Zeroable}; use std::mem; use vek::*; #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { pub pos: [f32; 3], } impl Vertex { fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { wgpu::VertexBufferLayout { array_stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, attributes: &[wgpu::VertexAttribute { offset: 0, shader_location: 0, format: wgpu::VertexFormat::Float32x3, }], } } } impl VertexTrait for Vertex { const QUADS_INDEX: Option = None; const STRIDE: wgpu::BufferAddress = mem::size_of::() as wgpu::BufferAddress; } #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Locals { /// pos is [f32; 4] instead of [f32; 3] so that Locals's size is a multiple /// of 8 bytes (which is required by gfx), the last component is ignored /// by the shader pub pos: [f32; 4], pub color: [f32; 4], } pub type BoundLocals = Bound>; impl From> for Vertex { fn from(pos: Vec3) -> Vertex { Vertex { pos: [pos.x, pos.y, pos.z], } } } pub struct DebugPipeline { pub pipeline: wgpu::RenderPipeline, } impl DebugPipeline { pub fn new( device: &wgpu::Device, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, global_layouts: &GlobalsLayouts, layout: &DebugLayout, aa_mode: AaMode, ) -> Self { common_base::span!(_guard, "DebugPipeline::new"); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Debug pipeline layout"), push_constant_ranges: &[], bind_group_layouts: &[&global_layouts.globals, &layout.locals], }); let samples = match aa_mode { AaMode::None | AaMode::Fxaa => 1, AaMode::MsaaX4 => 4, AaMode::MsaaX8 => 8, AaMode::MsaaX16 => 16, }; let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Debug pipeline"), layout: Some(&render_pipeline_layout), vertex: wgpu::VertexState { module: vs_module, entry_point: "main", buffers: &[Vertex::desc()], }, primitive: wgpu::PrimitiveState { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), clamp_depth: false, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, depth_stencil: Some(wgpu::DepthStencilState { format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: true, depth_compare: wgpu::CompareFunction::GreaterEqual, stencil: wgpu::StencilState { front: wgpu::StencilFaceState::IGNORE, back: wgpu::StencilFaceState::IGNORE, read_mask: !0, write_mask: !0, }, bias: wgpu::DepthBiasState { constant: 0, slope_scale: 0.0, clamp: 0.0, }, }), multisample: wgpu::MultisampleState { count: samples, mask: !0, alpha_to_coverage_enabled: false, }, fragment: Some(wgpu::FragmentState { module: fs_module, entry_point: "main", targets: &[wgpu::ColorTargetState { format: wgpu::TextureFormat::Rgba16Float, blend: Some(wgpu::BlendState::ALPHA_BLENDING), write_mask: wgpu::ColorWrite::ALL, }], }), }); Self { pipeline: render_pipeline, } } } pub struct DebugLayout { pub locals: wgpu::BindGroupLayout, } impl DebugLayout { pub fn new(device: &wgpu::Device) -> Self { Self { locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, entries: &[wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, min_binding_size: None, }, count: None, }], }), } } pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts) -> BoundLocals { let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: None, layout: &self.locals, entries: &[wgpu::BindGroupEntry { binding: 0, resource: locals.buf().as_entire_binding(), }], }); BoundLocals { bind_group, with: locals, } } }