diff options
Diffstat (limited to 'wgpu/src/window')
-rw-r--r-- | wgpu/src/window/compositor.rs | 158 |
1 files changed, 94 insertions, 64 deletions
diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index 6feb795b..a36d2a87 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -1,22 +1,27 @@ use crate::{Backend, Color, Error, Renderer, Settings, Viewport}; -use futures::task::SpawnExt; +use futures::stream::{self, StreamExt}; + +use iced_graphics::compositor; use iced_native::futures; use raw_window_handle::HasRawWindowHandle; +use std::marker::PhantomData; + /// A window graphics backend for iced powered by `wgpu`. #[allow(missing_debug_implementations)] -pub struct Compositor { +pub struct Compositor<Theme> { settings: Settings, instance: wgpu::Instance, + adapter: wgpu::Adapter, device: wgpu::Device, queue: wgpu::Queue, staging_belt: wgpu::util::StagingBelt, - local_pool: futures::executor::LocalPool, format: wgpu::TextureFormat, + theme: PhantomData<Theme>, } -impl Compositor { +impl<Theme> Compositor<Theme> { const CHUNK_SIZE: u64 = 10 * 1024; /// Requests a new [`Compositor`] with the given [`Settings`]. @@ -28,6 +33,17 @@ impl Compositor { ) -> Option<Self> { let instance = wgpu::Instance::new(settings.internal_backend); + log::info!("{:#?}", settings); + + #[cfg(not(target_arch = "wasm32"))] + if log::max_level() >= log::LevelFilter::Info { + let available_adapters: Vec<_> = instance + .enumerate_adapters(settings.internal_backend) + .map(|adapter| adapter.get_info()) + .collect(); + log::info!("Available adapters: {:#?}", available_adapters); + } + #[allow(unsafe_code)] let compatible_surface = compatible_window .map(|window| unsafe { instance.create_surface(window) }); @@ -44,45 +60,55 @@ impl Compositor { }) .await?; - let format = compatible_surface - .as_ref() - .and_then(|surface| surface.get_preferred_format(&adapter))?; + log::info!("Selected: {:#?}", adapter.get_info()); + + let format = compatible_surface.as_ref().and_then(|surface| { + surface.get_supported_formats(&adapter).first().copied() + })?; + + log::info!("Selected format: {:?}", format); #[cfg(target_arch = "wasm32")] - let limits = wgpu::Limits::downlevel_webgl2_defaults() - .using_resolution(adapter.limits()); + let limits = [wgpu::Limits::downlevel_webgl2_defaults() + .using_resolution(adapter.limits())]; #[cfg(not(target_arch = "wasm32"))] - let limits = wgpu::Limits::default(); - - let (device, queue) = adapter - .request_device( - &wgpu::DeviceDescriptor { - label: Some( - "iced_wgpu::window::compositor device descriptor", - ), - features: wgpu::Features::empty(), - limits: wgpu::Limits { - max_bind_groups: 2, - ..limits + let limits = + [wgpu::Limits::default(), wgpu::Limits::downlevel_defaults()]; + + let limits = limits.into_iter().map(|limits| wgpu::Limits { + max_bind_groups: 2, + ..limits + }); + + let (device, queue) = stream::iter(limits) + .filter_map(|limits| async { + adapter.request_device( + &wgpu::DeviceDescriptor { + label: Some( + "iced_wgpu::window::compositor device descriptor", + ), + features: wgpu::Features::empty(), + limits, }, - }, - None, - ) - .await - .ok()?; + None, + ).await.ok() + }) + .boxed() + .next() + .await?; let staging_belt = wgpu::util::StagingBelt::new(Self::CHUNK_SIZE); - let local_pool = futures::executor::LocalPool::new(); Some(Compositor { instance, settings, + adapter, device, queue, staging_belt, - local_pool, format, + theme: PhantomData, }) } @@ -92,20 +118,20 @@ impl Compositor { } } -impl iced_graphics::window::Compositor for Compositor { +impl<Theme> iced_graphics::window::Compositor for Compositor<Theme> { type Settings = Settings; - type Renderer = Renderer; + type Renderer = Renderer<Theme>; type Surface = wgpu::Surface; fn new<W: HasRawWindowHandle>( settings: Self::Settings, compatible_window: Option<&W>, - ) -> Result<(Self, Renderer), Error> { + ) -> Result<(Self, Self::Renderer), Error> { let compositor = futures::executor::block_on(Self::request( settings, compatible_window, )) - .ok_or(Error::AdapterNotFound)?; + .ok_or(Error::GraphicsAdapterNotFound)?; let backend = compositor.create_backend(); @@ -140,6 +166,15 @@ impl iced_graphics::window::Compositor for Compositor { ); } + fn fetch_information(&self) -> compositor::Information { + let information = self.adapter.get_info(); + + compositor::Information { + adapter: information.name, + backend: format!("{:?}", information.backend), + } + } + fn present<T: AsRef<str>>( &mut self, renderer: &mut Self::Renderer, @@ -147,7 +182,7 @@ impl iced_graphics::window::Compositor for Compositor { viewport: &Viewport, background_color: Color, overlay: &[T], - ) -> Result<(), iced_graphics::window::SurfaceError> { + ) -> Result<(), compositor::SurfaceError> { match surface.get_current_texture() { Ok(frame) => { let mut encoder = self.device.create_command_encoder( @@ -165,30 +200,32 @@ impl iced_graphics::window::Compositor for Compositor { label: Some( "iced_wgpu::window::Compositor render pass", ), - color_attachments: &[wgpu::RenderPassColorAttachment { - view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear({ - let [r, g, b, a] = - background_color.into_linear(); - - wgpu::Color { - r: f64::from(r), - g: f64::from(g), - b: f64::from(b), - a: f64::from(a), - } - }), - store: true, + color_attachments: &[Some( + wgpu::RenderPassColorAttachment { + view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear({ + let [r, g, b, a] = + background_color.into_linear(); + + wgpu::Color { + r: f64::from(r), + g: f64::from(g), + b: f64::from(b), + a: f64::from(a), + } + }), + store: true, + }, }, - }], + )], depth_stencil_attachment: None, }); renderer.with_primitives(|backend, primitives| { backend.present( - &mut self.device, + &self.device, &mut self.staging_belt, &mut encoder, view, @@ -200,31 +237,24 @@ impl iced_graphics::window::Compositor for Compositor { // Submit work self.staging_belt.finish(); - self.queue.submit(Some(encoder.finish())); + let _submission = self.queue.submit(Some(encoder.finish())); frame.present(); // Recall staging buffers - self.local_pool - .spawner() - .spawn(self.staging_belt.recall()) - .expect("Recall staging belt"); - - self.local_pool.run_until_stalled(); + self.staging_belt.recall(); Ok(()) } Err(error) => match error { wgpu::SurfaceError::Timeout => { - Err(iced_graphics::window::SurfaceError::Timeout) + Err(compositor::SurfaceError::Timeout) } wgpu::SurfaceError::Outdated => { - Err(iced_graphics::window::SurfaceError::Outdated) - } - wgpu::SurfaceError::Lost => { - Err(iced_graphics::window::SurfaceError::Lost) + Err(compositor::SurfaceError::Outdated) } + wgpu::SurfaceError::Lost => Err(compositor::SurfaceError::Lost), wgpu::SurfaceError::OutOfMemory => { - Err(iced_graphics::window::SurfaceError::OutOfMemory) + Err(compositor::SurfaceError::OutOfMemory) } }, } |