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 pub material_idx: u32,
19}
20
21unsafe impl bytemuck::Pod for PerObjectData {}
22unsafe impl bytemuck::Zeroable for PerObjectData {}
23
24pub struct ShaderInterfaces {
25 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}