wgpu_quick_start/
my_device.rs1use super::MyDevice;
6
7use super::GPUStarterResult;
8
9pub struct MyDeviceImpl<'a> {
52 surface: Option<wgpu::Surface<'a>>,
53
54 device: wgpu::Device,
55
56 queue: wgpu::Queue,
57
58 adapter: wgpu::Adapter,
59
60 config: Option<wgpu::SurfaceConfiguration>,
61
62 texture_format: wgpu::TextureFormat,
63}
64
65impl<'a> MyDeviceImpl<'a> {
66 #[cfg(feature = "enable-sync-winit")]
70 pub async fn new(
71 window: impl Into<wgpu::SurfaceTarget<'a>>,
72 dimensions: (u32, u32),
73 ) -> GPUStarterResult<Self> {
74 use crate::GPUInstance;
75 let instance = GPUInstance::new();
76 let surface = instance.create_surface(window)?;
77 let adapter = instance
78 .instance
79 .request_adapter(&wgpu::RequestAdapterOptions {
80 power_preference: wgpu::PowerPreference::default(),
81 compatible_surface: Some(&surface),
82 force_fallback_adapter: false,
83 })
84 .await?;
85
86 let (device, queue) = adapter
87 .request_device(&wgpu::DeviceDescriptor {
88 label: None,
89 required_features: wgpu::Features::empty(),
90 experimental_features: wgpu::ExperimentalFeatures::disabled(),
91
92 required_limits: if cfg!(target_arch = "wasm32") {
95 wgpu::Limits::downlevel_webgl2_defaults()
96 } else {
97 wgpu::Limits::default()
98 },
99 memory_hints: Default::default(),
100 trace: wgpu::Trace::Off,
101 })
102 .await?;
103
104 let surface_capabilities = surface.get_capabilities(&adapter);
105
106 let surface_format = surface_capabilities
110 .formats
111 .iter()
112 .find(|f| f.is_srgb())
113 .copied()
114 .unwrap_or(surface_capabilities.formats[0]);
115 let (width, height) = dimensions;
116 let config = wgpu::SurfaceConfiguration {
117 usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
118 format: surface_format,
119 width,
120 height,
121 present_mode: surface_capabilities.present_modes[0],
122 alpha_mode: surface_capabilities.alpha_modes[0],
123 view_formats: vec![],
124 desired_maximum_frame_latency: 2,
125 };
126
127 let surface_caps = surface.get_capabilities(&adapter);
128 let surface_format = surface_caps
129 .formats
130 .iter()
131 .copied()
132 .find(wgpu::TextureFormat::is_srgb)
133 .unwrap_or(surface_caps.formats[0]);
134
135 Ok(Self {
136 surface: Some(surface),
137 device,
138 queue,
139 adapter,
140 config: Some(config),
141 texture_format: surface_format,
142 })
143 }
144
145 #[cfg(feature = "enable-sync")]
148 pub async fn new_without_window() -> crate::GPUStarterResult<Self> {
149 let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
150 #[cfg(not(target_arch = "wasm32"))]
151 backends: wgpu::Backends::VULKAN,
152 #[cfg(target_arch = "wasm32")]
153 backends: wgpu::Backends::GL,
154 ..Default::default()
155 });
156 let adapter = instance
157 .request_adapter(&wgpu::RequestAdapterOptions {
158 power_preference: wgpu::PowerPreference::default(),
159 compatible_surface: None,
160 force_fallback_adapter: false,
161 })
162 .await?;
163 let (device, queue) = adapter.request_device(&Default::default()).await?;
164 let texture_size = 256u32;
165
166 let texture_desc = wgpu::TextureDescriptor {
167 size: wgpu::Extent3d {
168 width: texture_size,
169 height: texture_size,
170 depth_or_array_layers: 1,
171 },
172 view_formats: &[],
173 mip_level_count: 1,
174 sample_count: 1,
175 dimension: wgpu::TextureDimension::D2,
176 format: wgpu::TextureFormat::Rgba8UnormSrgb,
177 usage: wgpu::TextureUsages::COPY_SRC | wgpu::TextureUsages::RENDER_ATTACHMENT,
178 label: None,
179 };
180 let texture = device.create_texture(&texture_desc);
181 let _texture_view = texture.create_view(&Default::default());
182 Ok(Self {
183 surface: None,
184 device,
185 queue,
186 adapter,
187 config: None,
188 texture_format: texture.format(),
189 })
190 }
191}
192
193impl<'a> MyDevice for MyDeviceImpl<'a> {
194 fn get_device(&self) -> &wgpu::Device {
195 &self.device
196 }
197
198 fn get_queue(&self) -> &wgpu::Queue {
199 &self.queue
200 }
201
202 fn get_adapter(&self) -> &wgpu::Adapter {
203 &self.adapter
204 }
205
206 fn get_current_texture(&self) -> GPUStarterResult<wgpu::SurfaceTexture> {
207 if let Some(surface) = self.surface.as_ref() {
208 let output = surface.get_current_texture()?;
209 Ok(output)
210 } else {
211 Err(crate::GPUStarterError::UnsupportedError)
212 }
213 }
214
215 fn get_texture_format(&self) -> GPUStarterResult<wgpu::TextureFormat> {
216 Ok(self.texture_format)
217 }
218
219 fn resize(&mut self, dimensions: (u32, u32)) {
220 let (width, height) = dimensions;
222 if let Some(surface) = self.surface.as_mut()
223 && let Some(config) = self.config.as_mut()
224 && width > 0
225 && height > 0
226 {
227 config.width = width;
228 config.height = height;
229 surface.configure(&self.device, config);
230 }
231 }
232}
233
234#[cfg(test)]
235mod tests {
236
237 #[test]
238 #[ignore = "bug with adapter Vulkan/GL support etc"]
239 #[cfg(feature = "enable-sync")]
240 fn test_windowless_device() -> super::super::GPUStarterResult<()> {
241 use super::*;
242 let my_device = pollster::block_on(MyDeviceImpl::new_without_window())?;
243 assert!(my_device.get_texture_format().is_ok());
244 Ok(())
245 }
246}