rend3_pbr/
utils.rs

1use std::convert::TryFrom;
2
3use glam::UVec2;
4use wgpu::{
5    Device, Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages, TextureView,
6    TextureViewDescriptor,
7};
8
9#[derive(Debug, Copy, Clone, PartialEq, Eq)]
10pub struct RenderTextureOptions {
11    pub resolution: UVec2,
12    pub samples: SampleCount,
13}
14
15#[derive(Debug, Copy, Clone, PartialEq, Eq)]
16#[repr(u8)]
17pub enum SampleCount {
18    One = 1,
19    Four = 4,
20}
21
22impl Default for SampleCount {
23    fn default() -> Self {
24        Self::One
25    }
26}
27
28impl TryFrom<u8> for SampleCount {
29    type Error = u8;
30
31    fn try_from(value: u8) -> Result<Self, Self::Error> {
32        Ok(match value {
33            1 => Self::One,
34            4 => Self::Four,
35            v => return Err(v),
36        })
37    }
38}
39
40pub struct RenderTextures {
41    pub color: TextureView,
42    pub resolve: Option<TextureView>,
43    pub depth: TextureView,
44    pub samples: SampleCount,
45}
46impl RenderTextures {
47    pub fn new(device: &Device, options: RenderTextureOptions) -> Self {
48        profiling::scope!("RenderTextures::new");
49        Self {
50            color: create_internal_color_buffer(
51                device,
52                TextureFormat::Rgba16Float,
53                options.resolution,
54                options.samples,
55            ),
56            resolve: if options.samples != SampleCount::One {
57                Some(create_internal_color_buffer(
58                    device,
59                    TextureFormat::Rgba16Float,
60                    options.resolution,
61                    SampleCount::One,
62                ))
63            } else {
64                None
65            },
66            depth: create_internal_depth_buffer(device, options),
67            samples: options.samples,
68        }
69    }
70
71    pub fn blit_source_view(&self) -> &TextureView {
72        self.resolve.as_ref().unwrap_or(&self.color)
73    }
74}
75
76fn create_internal_color_buffer(
77    device: &Device,
78    format: TextureFormat,
79    resolution: UVec2,
80    samples: SampleCount,
81) -> TextureView {
82    device
83        .create_texture(&TextureDescriptor {
84            label: Some("internal renderbuffer"),
85            size: Extent3d {
86                width: resolution.x,
87                height: resolution.y,
88                depth_or_array_layers: 1,
89            },
90            mip_level_count: 1,
91            sample_count: samples as u32,
92            dimension: TextureDimension::D2,
93            format,
94            usage: TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_SRC,
95        })
96        .create_view(&TextureViewDescriptor::default())
97}
98
99fn create_internal_depth_buffer(device: &Device, options: RenderTextureOptions) -> TextureView {
100    device
101        .create_texture(&TextureDescriptor {
102            label: Some("internal depth renderbuffer"),
103            size: Extent3d {
104                width: options.resolution.x,
105                height: options.resolution.y,
106                depth_or_array_layers: 1,
107            },
108            mip_level_count: 1,
109            sample_count: options.samples as u32,
110            dimension: TextureDimension::D2,
111            format: TextureFormat::Depth32Float,
112            usage: TextureUsages::RENDER_ATTACHMENT,
113        })
114        .create_view(&TextureViewDescriptor::default())
115}