veloren_voxygen/render/pipelines/
debug.rs

1use super::super::{AaMode, Bound, Consts, GlobalsLayouts, Vertex as VertexTrait};
2use bytemuck::{Pod, Zeroable};
3use std::mem;
4use vek::*;
5
6#[repr(C)]
7#[derive(Copy, Clone, Debug, Zeroable, Pod)]
8pub struct Vertex {
9    pub pos: [f32; 3],
10    pub color: [f32; 4],
11    pub normal: [f32; 3],
12}
13
14impl Vertex {
15    pub fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
16        const ATTRIBUTES: [wgpu::VertexAttribute; 3] =
17            wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x4, 2 => Float32x3];
18        wgpu::VertexBufferLayout {
19            array_stride: Self::STRIDE,
20            step_mode: wgpu::VertexStepMode::Vertex,
21            attributes: &ATTRIBUTES,
22        }
23    }
24}
25
26impl VertexTrait for Vertex {
27    const QUADS_INDEX: Option<wgpu::IndexFormat> = None;
28    const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
29}
30
31#[repr(C)]
32#[derive(Copy, Clone, Debug, Zeroable, Pod)]
33pub struct Locals {
34    /// pos is [f32; 4] instead of [f32; 3] so that Locals' size is a multiple
35    /// of 8 bytes (which is required by gfx), the last component is ignored
36    /// by the shader
37    pub pos: [f32; 4],
38    pub color: [f32; 4],
39    /// quaternion as [x, y, z, w]
40    pub ori: [f32; 4],
41}
42
43pub type BoundLocals = Bound<Consts<Locals>>;
44
45impl From<Vec3<f32>> for Vertex {
46    fn from(pos: Vec3<f32>) -> Vertex {
47        Vertex {
48            pos: [pos.x, pos.y, pos.z],
49            color: [1.0; 4],
50            normal: [0.0, 0.0, 1.0],
51        }
52    }
53}
54
55impl From<(Vec3<f32>, [f32; 4], Vec3<f32>)> for Vertex {
56    fn from((pos, color, normal): (Vec3<f32>, [f32; 4], Vec3<f32>)) -> Vertex {
57        Vertex {
58            pos: [pos.x, pos.y, pos.z],
59            color,
60            normal: [normal.x, normal.y, normal.z],
61        }
62    }
63}
64
65pub struct DebugPipeline {
66    pub pipeline: wgpu::RenderPipeline,
67}
68
69impl DebugPipeline {
70    pub fn new(
71        device: &wgpu::Device,
72        vs_module: &wgpu::ShaderModule,
73        fs_module: &wgpu::ShaderModule,
74        global_layouts: &GlobalsLayouts,
75        layout: &DebugLayout,
76        aa_mode: AaMode,
77        format: wgpu::TextureFormat,
78    ) -> Self {
79        common_base::span!(_guard, "DebugPipeline::new");
80        let render_pipeline_layout =
81            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
82                label: Some("Debug pipeline layout"),
83                push_constant_ranges: &[],
84                bind_group_layouts: &[
85                    &global_layouts.globals,
86                    &global_layouts.shadow_textures,
87                    &layout.locals,
88                ],
89            });
90
91        let samples = aa_mode.samples();
92
93        let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
94            label: Some("Debug pipeline"),
95            layout: Some(&render_pipeline_layout),
96            vertex: wgpu::VertexState {
97                module: vs_module,
98                entry_point: "main",
99                buffers: &[Vertex::desc()],
100            },
101            primitive: wgpu::PrimitiveState {
102                topology: wgpu::PrimitiveTopology::TriangleList,
103                strip_index_format: None,
104                front_face: wgpu::FrontFace::Ccw,
105                cull_mode: Some(wgpu::Face::Back),
106                unclipped_depth: true,
107                polygon_mode: wgpu::PolygonMode::Fill,
108                conservative: false,
109            },
110            depth_stencil: Some(wgpu::DepthStencilState {
111                format: wgpu::TextureFormat::Depth32Float,
112                depth_write_enabled: true,
113                depth_compare: wgpu::CompareFunction::GreaterEqual,
114                stencil: wgpu::StencilState {
115                    front: wgpu::StencilFaceState::IGNORE,
116                    back: wgpu::StencilFaceState::IGNORE,
117                    read_mask: !0,
118                    write_mask: 0,
119                },
120                bias: wgpu::DepthBiasState {
121                    constant: 0,
122                    slope_scale: 0.0,
123                    clamp: 0.0,
124                },
125            }),
126            multisample: wgpu::MultisampleState {
127                count: samples,
128                mask: !0,
129                alpha_to_coverage_enabled: false,
130            },
131            fragment: Some(wgpu::FragmentState {
132                module: fs_module,
133                entry_point: "main",
134                targets: &[
135                    Some(wgpu::ColorTargetState {
136                        format,
137                        blend: Some(wgpu::BlendState::ALPHA_BLENDING),
138                        write_mask: wgpu::ColorWrites::ALL,
139                    }),
140                    Some(wgpu::ColorTargetState {
141                        format: wgpu::TextureFormat::Rgba8Uint,
142                        blend: None,
143                        write_mask: wgpu::ColorWrites::empty(),
144                    }),
145                ],
146            }),
147            multiview: None,
148        });
149
150        Self {
151            pipeline: render_pipeline,
152        }
153    }
154}
155
156pub struct DebugLayout {
157    pub locals: wgpu::BindGroupLayout,
158}
159
160impl DebugLayout {
161    pub fn new(device: &wgpu::Device) -> Self {
162        Self {
163            locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
164                label: None,
165                entries: &[wgpu::BindGroupLayoutEntry {
166                    binding: 0,
167                    visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
168                    ty: wgpu::BindingType::Buffer {
169                        ty: wgpu::BufferBindingType::Uniform,
170                        has_dynamic_offset: false,
171                        min_binding_size: None,
172                    },
173                    count: None,
174                }],
175            }),
176        }
177    }
178
179    pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts<Locals>) -> BoundLocals {
180        let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
181            label: None,
182            layout: &self.locals,
183            entries: &[wgpu::BindGroupEntry {
184                binding: 0,
185                resource: locals.buf().as_entire_binding(),
186            }],
187        });
188
189        BoundLocals {
190            bind_group,
191            with: locals,
192        }
193    }
194}