rend3_routine/common/
interfaces.rs

1use std::{marker::PhantomData, mem, num::NonZeroU64};
2
3use glam::{Mat4, Vec3};
4use rend3::{
5    managers::{DirectionalLightManager, MaterialManager},
6    types::Material,
7    util::bind_merge::BindGroupLayoutBuilder,
8    RendererProfile,
9};
10use wgpu::{BindGroupLayout, BindingType, BufferBindingType, Device, ShaderStages};
11
12use crate::{common::samplers::Samplers, uniforms::FrameUniforms};
13
14/// Interfaces which are used throughout the whole frame.
15///
16/// Contains the samplers, per frame uniforms, and directional light
17/// information.
18pub struct WholeFrameInterfaces {
19    /// Includes everything excluding the directional light information to
20    /// prevent cycles when rendering to shadow maps.
21    pub depth_uniform_bgl: BindGroupLayout,
22    /// Includes everything.
23    pub forward_uniform_bgl: BindGroupLayout,
24}
25
26impl WholeFrameInterfaces {
27    pub fn new(device: &Device) -> Self {
28        profiling::scope!("ShaderInterfaces::new");
29
30        let mut uniform_bglb = BindGroupLayoutBuilder::new();
31
32        Samplers::add_to_bgl(&mut uniform_bglb);
33
34        uniform_bglb.append(
35            ShaderStages::VERTEX_FRAGMENT,
36            BindingType::Buffer {
37                ty: BufferBindingType::Uniform,
38                has_dynamic_offset: false,
39                min_binding_size: NonZeroU64::new(mem::size_of::<FrameUniforms>() as _),
40            },
41            None,
42        );
43
44        let shadow_uniform_bgl = uniform_bglb.build(device, Some("shadow uniform bgl"));
45
46        DirectionalLightManager::add_to_bgl(&mut uniform_bglb);
47
48        let forward_uniform_bgl = uniform_bglb.build(device, Some("forward uniform bgl"));
49
50        Self {
51            depth_uniform_bgl: shadow_uniform_bgl,
52            forward_uniform_bgl,
53        }
54    }
55}
56
57/// The input structure that the culling shaders/functions output and drawing
58/// shaders read.
59#[repr(C, align(16))]
60#[derive(Debug, Copy, Clone)]
61pub struct PerObjectDataAbi {
62    pub model_view: Mat4,
63    pub model_view_proj: Mat4,
64    // Only read when GpuDriven. Materials are directly bound when CpuDriven.
65    pub material_idx: u32,
66    pub pad0: [u8; 12],
67    pub inv_squared_scale: Vec3,
68}
69
70unsafe impl bytemuck::Pod for PerObjectDataAbi {}
71unsafe impl bytemuck::Zeroable for PerObjectDataAbi {}
72
73/// Interface which has all per-material-archetype data: the object output
74/// buffer and the gpu material buffer.
75pub struct PerMaterialArchetypeInterface<M> {
76    pub bgl: BindGroupLayout,
77    _phantom: PhantomData<M>,
78}
79impl<M: Material> PerMaterialArchetypeInterface<M> {
80    pub fn new(device: &Device, profile: RendererProfile) -> Self {
81        let mut per_material_bglb = BindGroupLayoutBuilder::new();
82
83        per_material_bglb.append(
84            ShaderStages::VERTEX,
85            BindingType::Buffer {
86                ty: BufferBindingType::Storage { read_only: true },
87                has_dynamic_offset: false,
88                min_binding_size: NonZeroU64::new(mem::size_of::<PerObjectDataAbi>() as _),
89            },
90            None,
91        );
92
93        if profile == RendererProfile::GpuDriven {
94            MaterialManager::add_to_bgl_gpu::<M>(&mut per_material_bglb);
95        }
96
97        let bgl = per_material_bglb.build(device, Some("per material bgl"));
98
99        Self {
100            bgl,
101            _phantom: PhantomData,
102        }
103    }
104}