1use std::{num::NonZero, time::Instant};
5
6use wgpu::util::TextureBlitter;
7
8const TEXTURE_SIZE: u32 = 512;
9
10const LAYER_MASK: u32 = 0b11;
12
13const NUM_LAYERS: u32 = 32 - LAYER_MASK.leading_zeros();
14
15pub struct Example {
16 pipeline: wgpu::RenderPipeline,
17 entire_texture_view: wgpu::TextureView,
18 views: Vec<wgpu::TextureView>,
19 start_time: Instant,
20 blitter: TextureBlitter,
21}
22
23impl crate::framework::Example for Example {
24 fn init(
25 config: &wgpu::SurfaceConfiguration,
26 _adapter: &wgpu::Adapter,
27 device: &wgpu::Device,
28 _queue: &wgpu::Queue,
29 ) -> Self {
30 let shader_src = include_str!("shader.wgsl");
31
32 let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
33 label: None,
34 source: wgpu::ShaderSource::Wgsl(shader_src.into()),
35 });
36
37 let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
38 label: None,
39 vertex: wgpu::VertexState {
40 buffers: &[],
41 module: &shader,
42 entry_point: Some("vs_main"),
43 compilation_options: Default::default(),
44 },
45 primitive: wgpu::PrimitiveState::default(),
46 fragment: Some(wgpu::FragmentState {
47 module: &shader,
48 entry_point: Some("fs_main"),
49 compilation_options: Default::default(),
50 targets: &[Some(wgpu::ColorTargetState {
51 format: wgpu::TextureFormat::Rgba8Unorm,
52 blend: None,
53 write_mask: wgpu::ColorWrites::ALL,
54 })],
55 }),
56 multiview_mask: NonZero::new(LAYER_MASK),
57 multisample: Default::default(),
58 layout: None,
59 depth_stencil: None,
60 cache: None,
61 });
62 let texture = device.create_texture(&wgpu::TextureDescriptor {
63 label: None,
64 size: wgpu::Extent3d {
65 width: TEXTURE_SIZE,
66 height: TEXTURE_SIZE,
67 depth_or_array_layers: NUM_LAYERS,
68 },
69 mip_level_count: 1,
70 sample_count: 1,
71 dimension: wgpu::TextureDimension::D2,
72 format: wgpu::TextureFormat::Rgba8Unorm,
73 usage: wgpu::TextureUsages::RENDER_ATTACHMENT
74 | wgpu::TextureUsages::COPY_SRC
75 | wgpu::TextureUsages::TEXTURE_BINDING,
76 view_formats: &[],
77 });
78 let entire_texture_view = texture.create_view(&wgpu::TextureViewDescriptor {
79 label: None,
80 format: Some(wgpu::TextureFormat::Rgba8Unorm),
81 dimension: Some(wgpu::TextureViewDimension::D2Array),
82 usage: Some(wgpu::TextureUsages::RENDER_ATTACHMENT),
83 aspect: wgpu::TextureAspect::All,
84 base_mip_level: 0,
85 mip_level_count: None,
86 base_array_layer: 0,
87 array_layer_count: Some(NUM_LAYERS),
88 });
89 let mut views = Vec::new();
90 for i in 0..NUM_LAYERS {
91 views.push(texture.create_view(&wgpu::TextureViewDescriptor {
92 label: None,
93 format: Some(wgpu::TextureFormat::Rgba8Unorm),
94 dimension: Some(wgpu::TextureViewDimension::D2),
95 usage: Some(wgpu::TextureUsages::TEXTURE_BINDING),
96 aspect: wgpu::TextureAspect::All,
97 base_mip_level: 0,
98 mip_level_count: None,
99 base_array_layer: i,
100 array_layer_count: Some(1),
101 }));
102 }
103 let blitter = wgpu::util::TextureBlitter::new(device, config.format);
104 Self {
105 pipeline,
106 entire_texture_view,
107 views,
108 blitter,
109 start_time: Instant::now(),
110 }
111 }
112
113 fn render(&mut self, view: &wgpu::TextureView, device: &wgpu::Device, queue: &wgpu::Queue) {
114 let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
115 {
116 let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
117 label: None,
118 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
119 view: &self.entire_texture_view,
120 depth_slice: None,
121 resolve_target: None,
122 ops: wgpu::Operations {
123 load: wgpu::LoadOp::Clear(wgpu::Color {
124 r: 0.02,
125 g: 0.02,
126 b: 0.02,
127 a: 1.0,
128 }),
129 store: wgpu::StoreOp::Store,
130 },
131 })],
132 depth_stencil_attachment: None,
133 timestamp_writes: None,
134 occlusion_query_set: None,
135 multiview_mask: NonZero::new(LAYER_MASK),
136 });
137 rpass.set_pipeline(&self.pipeline);
138 rpass.draw(0..6, 0..1);
139 }
140
141 let layer = (Instant::now() - self.start_time).as_secs() % NUM_LAYERS as u64;
142 self.blitter
143 .copy(device, &mut encoder, &self.views[layer as usize], view);
144 queue.submit(Some(encoder.finish()));
145 }
146
147 fn required_downlevel_capabilities() -> wgpu::DownlevelCapabilities {
148 Default::default()
149 }
150
151 fn required_features() -> wgpu::Features {
152 wgpu::Features::MULTIVIEW
153 | if !(LAYER_MASK + 1).is_power_of_two() {
154 wgpu::Features::SELECTIVE_MULTIVIEW
155 } else {
156 wgpu::Features::empty()
157 }
158 }
159
160 fn required_limits() -> wgpu::Limits {
161 wgpu::Limits {
162 max_multiview_view_count: NUM_LAYERS,
163 ..Default::default()
164 }
165 }
166
167 fn resize(
168 &mut self,
169 _config: &wgpu::SurfaceConfiguration,
170 _device: &wgpu::Device,
171 _queue: &wgpu::Queue,
172 ) {
173 }
175 fn update(&mut self, _event: winit::event::WindowEvent) {
176 }
178}
179
180pub fn main() {
181 crate::framework::run::<Example>("multiview");
182}