rend3_pbr/common/
interfaces.rs

1use std::{mem, num::NonZeroU64};
2
3use glam::{Mat3A, Mat4};
4use wgpu::{
5    BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BufferBindingType, Device,
6    ShaderStages, TextureSampleType, TextureViewDimension,
7};
8
9use crate::uniforms::ShaderCommonUniform;
10
11#[repr(C, align(16))]
12#[derive(Debug, Copy, Clone)]
13pub struct PerObjectData {
14    pub model_view: Mat4,
15    pub model_view_proj: Mat4,
16    pub inv_trans_model_view: Mat3A,
17    // Unused in shader
18    pub material_idx: u32,
19}
20
21unsafe impl bytemuck::Pod for PerObjectData {}
22unsafe impl bytemuck::Zeroable for PerObjectData {}
23
24pub struct ShaderInterfaces {
25    // TODO: move this into samplers struct, in cpu mode this should only bind 2 samplers
26    pub samplers_bgl: BindGroupLayout,
27    pub culled_object_bgl: BindGroupLayout,
28    pub uniform_bgl: BindGroupLayout,
29    pub blit_bgl: BindGroupLayout,
30    pub skybox_bgl: BindGroupLayout,
31}
32
33impl ShaderInterfaces {
34    pub fn new(device: &Device) -> Self {
35        profiling::scope!("ShaderInterfaces::new");
36
37        let samplers_bgl = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
38            label: Some("samplers bgl"),
39            entries: &[
40                BindGroupLayoutEntry {
41                    binding: 0,
42                    visibility: ShaderStages::FRAGMENT,
43                    ty: BindingType::Sampler {
44                        filtering: true,
45                        comparison: false,
46                    },
47                    count: None,
48                },
49                BindGroupLayoutEntry {
50                    binding: 1,
51                    visibility: ShaderStages::FRAGMENT,
52                    ty: BindingType::Sampler {
53                        filtering: true,
54                        comparison: false,
55                    },
56                    count: None,
57                },
58                BindGroupLayoutEntry {
59                    binding: 2,
60                    visibility: ShaderStages::FRAGMENT,
61                    ty: BindingType::Sampler {
62                        filtering: true,
63                        comparison: true,
64                    },
65                    count: None,
66                },
67            ],
68        });
69
70        let culled_object_bgl = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
71            label: Some("culled object bgl"),
72            entries: &[BindGroupLayoutEntry {
73                binding: 0,
74                visibility: ShaderStages::VERTEX,
75                ty: BindingType::Buffer {
76                    ty: BufferBindingType::Storage { read_only: true },
77                    has_dynamic_offset: false,
78                    min_binding_size: NonZeroU64::new(mem::size_of::<PerObjectData>() as _),
79                },
80                count: None,
81            }],
82        });
83
84        let uniform_bgl = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
85            label: Some("uniform bgl"),
86            entries: &[BindGroupLayoutEntry {
87                binding: 0,
88                visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
89                ty: BindingType::Buffer {
90                    ty: BufferBindingType::Uniform,
91                    has_dynamic_offset: false,
92                    min_binding_size: NonZeroU64::new(mem::size_of::<ShaderCommonUniform>() as _),
93                },
94                count: None,
95            }],
96        });
97
98        let blit_bgl = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
99            label: Some("blit bgl"),
100            entries: &[BindGroupLayoutEntry {
101                binding: 0,
102                visibility: ShaderStages::FRAGMENT,
103                ty: BindingType::Texture {
104                    sample_type: TextureSampleType::Float { filterable: true },
105                    view_dimension: TextureViewDimension::D2,
106                    multisampled: false,
107                },
108                count: None,
109            }],
110        });
111
112        let skybox_bgl = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
113            label: Some("skybox bgl"),
114            entries: &[BindGroupLayoutEntry {
115                binding: 0,
116                visibility: ShaderStages::FRAGMENT,
117                ty: BindingType::Texture {
118                    sample_type: TextureSampleType::Float { filterable: true },
119                    view_dimension: TextureViewDimension::Cube,
120                    multisampled: false,
121                },
122                count: None,
123            }],
124        });
125
126        Self {
127            samplers_bgl,
128            culled_object_bgl,
129            uniform_bgl,
130            blit_bgl,
131            skybox_bgl,
132        }
133    }
134}