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}