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: Some("main"),
99                buffers: &[Vertex::desc()],
100                compilation_options: Default::default(),
101            },
102            primitive: wgpu::PrimitiveState {
103                topology: wgpu::PrimitiveTopology::TriangleList,
104                strip_index_format: None,
105                front_face: wgpu::FrontFace::Ccw,
106                cull_mode: Some(wgpu::Face::Back),
107                unclipped_depth: true,
108                polygon_mode: wgpu::PolygonMode::Fill,
109                conservative: false,
110            },
111            depth_stencil: Some(wgpu::DepthStencilState {
112                format: wgpu::TextureFormat::Depth32Float,
113                depth_write_enabled: true,
114                depth_compare: wgpu::CompareFunction::GreaterEqual,
115                stencil: wgpu::StencilState {
116                    front: wgpu::StencilFaceState::IGNORE,
117                    back: wgpu::StencilFaceState::IGNORE,
118                    read_mask: !0,
119                    write_mask: 0,
120                },
121                bias: wgpu::DepthBiasState {
122                    constant: 0,
123                    slope_scale: 0.0,
124                    clamp: 0.0,
125                },
126            }),
127            multisample: wgpu::MultisampleState {
128                count: samples,
129                mask: !0,
130                alpha_to_coverage_enabled: false,
131            },
132            fragment: Some(wgpu::FragmentState {
133                module: fs_module,
134                entry_point: Some("main"),
135                targets: &[
136                    Some(wgpu::ColorTargetState {
137                        format,
138                        blend: Some(wgpu::BlendState::ALPHA_BLENDING),
139                        write_mask: wgpu::ColorWrites::ALL,
140                    }),
141                    Some(wgpu::ColorTargetState {
142                        format: wgpu::TextureFormat::Rgba8Uint,
143                        blend: None,
144                        write_mask: wgpu::ColorWrites::empty(),
145                    }),
146                ],
147                compilation_options: Default::default(),
148            }),
149            multiview: None,
150            cache: None,
151        });
152
153        Self {
154            pipeline: render_pipeline,
155        }
156    }
157}
158
159pub struct DebugLayout {
160    pub locals: wgpu::BindGroupLayout,
161}
162
163impl DebugLayout {
164    pub fn new(device: &wgpu::Device) -> Self {
165        Self {
166            locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
167                label: None,
168                entries: &[wgpu::BindGroupLayoutEntry {
169                    binding: 0,
170                    visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
171                    ty: wgpu::BindingType::Buffer {
172                        ty: wgpu::BufferBindingType::Uniform,
173                        has_dynamic_offset: false,
174                        min_binding_size: None,
175                    },
176                    count: None,
177                }],
178            }),
179        }
180    }
181
182    pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts<Locals>) -> BoundLocals {
183        let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
184            label: None,
185            layout: &self.locals,
186            entries: &[wgpu::BindGroupEntry {
187                binding: 0,
188                resource: locals.buf().as_entire_binding(),
189            }],
190        });
191
192        BoundLocals {
193            bind_group,
194            with: locals,
195        }
196    }
197}