From 91d46ecc2be410081ce4db4799215c24984620dc Mon Sep 17 00:00:00 2001 From: AlphaModder Date: Sun, 24 May 2020 19:35:48 -0700 Subject: [PATCH] Rename SwapChain::get_next_texture to SwapChain::get_next_frame, and have it return errors to the user. --- Cargo.toml | 4 +- examples/boids/main.rs | 2 +- examples/capture/main.rs | 2 +- examples/cube/main.rs | 2 +- examples/framework.rs | 18 +++-- examples/hello-compute/main.rs | 2 +- examples/hello-triangle/main.rs | 5 +- examples/mipmap/main.rs | 2 +- examples/msaa-line/main.rs | 2 +- examples/shadow/main.rs | 2 +- examples/skybox/main.rs | 2 +- src/backend/direct.rs | 44 +++++----- src/backend/web.rs | 31 ++++---- src/lib.rs | 137 ++++++++++++++++++-------------- 14 files changed, 138 insertions(+), 117 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2071baa369..f861fd6efc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,14 +28,14 @@ vulkan = ["wgc/gfx-backend-vulkan"] package = "wgpu-core" version = "0.5" git = "https://github.com/gfx-rs/wgpu" -rev = "4e1d76013c0b272383400beba48dc306e1a350f6" +rev = "a6d468086dc48683d0c97b9e3b63264ad67660da" features = ["raw-window-handle"] [dependencies.wgt] package = "wgpu-types" version = "0.5" git = "https://github.com/gfx-rs/wgpu" -rev = "4e1d76013c0b272383400beba48dc306e1a350f6" +rev = "a6d468086dc48683d0c97b9e3b63264ad67660da" [dependencies] arrayvec = "0.5" diff --git a/examples/boids/main.rs b/examples/boids/main.rs index c68c47066d..d52a5defd6 100644 --- a/examples/boids/main.rs +++ b/examples/boids/main.rs @@ -259,7 +259,7 @@ impl framework::Example for Example { /// a TriangleList draw call for all NUM_PARTICLES at 3 vertices each fn render( &mut self, - frame: &wgpu::SwapChainOutput, + frame: &wgpu::SwapChainTexture, device: &wgpu::Device, _queue: &wgpu::Queue, ) -> wgpu::CommandBuffer { diff --git a/examples/capture/main.rs b/examples/capture/main.rs index dff4ea2845..cde29eb4a9 100644 --- a/examples/capture/main.rs +++ b/examples/capture/main.rs @@ -95,7 +95,7 @@ async fn run() { queue.submit(Some(command_buffer)); // Note that we're not calling `.await` here. - let buffer_future = output_buffer.map_read(0, (size * size) as u64 * size_of::() as u64); + let buffer_future = output_buffer.map_read(0, wgt::BufferSize::WHOLE); // Poll the device in a blocking manner so that our future resolves. // In an actual application, `device.poll(...)` should diff --git a/examples/cube/main.rs b/examples/cube/main.rs index 811549ec06..7728fc7b74 100644 --- a/examples/cube/main.rs +++ b/examples/cube/main.rs @@ -319,7 +319,7 @@ impl framework::Example for Example { fn render( &mut self, - frame: &wgpu::SwapChainOutput, + frame: &wgpu::SwapChainTexture, device: &wgpu::Device, _queue: &wgpu::Queue, ) -> wgpu::CommandBuffer { diff --git a/examples/framework.rs b/examples/framework.rs index 69d9454832..0584526a79 100644 --- a/examples/framework.rs +++ b/examples/framework.rs @@ -44,7 +44,7 @@ pub trait Example: 'static + Sized { fn update(&mut self, event: WindowEvent); fn render( &mut self, - frame: &wgpu::SwapChainOutput, + frame: &wgpu::SwapChainTexture, device: &wgpu::Device, queue: &wgpu::Queue, ) -> wgpu::CommandBuffer; @@ -143,7 +143,6 @@ async fn run_async(event_loop: EventLoop<()>, window: Window) { log::info!("Resizing to {:?}", size); sc_desc.width = size.width; sc_desc.height = size.height; - swap_chain = device.create_swap_chain(&surface, &sc_desc); example.resize(&sc_desc, &device, &queue); } event::Event::WindowEvent { event, .. } => match event { @@ -164,10 +163,17 @@ async fn run_async(event_loop: EventLoop<()>, window: Window) { } }, event::Event::RedrawRequested(_) => { - let frame = swap_chain - .get_next_texture() - .expect("Timeout when acquiring next swap chain texture"); - let command_buf = example.render(&frame, &device, &queue); + let frame = match swap_chain.get_next_frame() { + Ok(frame) => frame, + Err(_) => { + swap_chain = device.create_swap_chain(&surface, &sc_desc); + swap_chain + .get_next_frame() + .expect("Failed to acquire next swap chain texture!") + } + }; + + let command_buf = example.render(&frame.output, &device, &queue); queue.submit(Some(command_buf)); } _ => {} diff --git a/examples/hello-compute/main.rs b/examples/hello-compute/main.rs index 2273c3debc..893dfb7bbf 100644 --- a/examples/hello-compute/main.rs +++ b/examples/hello-compute/main.rs @@ -111,7 +111,7 @@ async fn execute_gpu(numbers: Vec) -> Vec { queue.submit(Some(encoder.finish())); // Note that we're not calling `.await` here. - let buffer_future = staging_buffer.map_read(0, size); + let buffer_future = staging_buffer.map_read(0, wgt::BufferSize::WHOLE); // Poll the device in a blocking manner so that our future resolves. // In an actual application, `device.poll(...)` should diff --git a/examples/hello-triangle/main.rs b/examples/hello-triangle/main.rs index 2b44bb8e85..f6b9a2461d 100644 --- a/examples/hello-triangle/main.rs +++ b/examples/hello-triangle/main.rs @@ -110,8 +110,9 @@ async fn run(event_loop: EventLoop<()>, window: Window, swapchain_format: wgpu:: } Event::RedrawRequested(_) => { let frame = swap_chain - .get_next_texture() - .expect("Timeout when acquiring next swap chain texture"); + .get_next_frame() + .expect("Failed to acquire next swap chain texture") + .output; let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); { diff --git a/examples/mipmap/main.rs b/examples/mipmap/main.rs index 5aeb3cb34d..d6e14f9bf4 100644 --- a/examples/mipmap/main.rs +++ b/examples/mipmap/main.rs @@ -412,7 +412,7 @@ impl framework::Example for Example { fn render( &mut self, - frame: &wgpu::SwapChainOutput, + frame: &wgpu::SwapChainTexture, device: &wgpu::Device, _queue: &wgpu::Queue, ) -> wgpu::CommandBuffer { diff --git a/examples/msaa-line/main.rs b/examples/msaa-line/main.rs index 493a2ed73e..c33d045c0f 100644 --- a/examples/msaa-line/main.rs +++ b/examples/msaa-line/main.rs @@ -218,7 +218,7 @@ impl framework::Example for Example { fn render( &mut self, - frame: &wgpu::SwapChainOutput, + frame: &wgpu::SwapChainTexture, device: &wgpu::Device, _queue: &wgpu::Queue, ) -> wgpu::CommandBuffer { diff --git a/examples/shadow/main.rs b/examples/shadow/main.rs index 783aa7157f..b2165be8dd 100644 --- a/examples/shadow/main.rs +++ b/examples/shadow/main.rs @@ -698,7 +698,7 @@ impl framework::Example for Example { fn render( &mut self, - frame: &wgpu::SwapChainOutput, + frame: &wgpu::SwapChainTexture, device: &wgpu::Device, queue: &wgpu::Queue, ) -> wgpu::CommandBuffer { diff --git a/examples/skybox/main.rs b/examples/skybox/main.rs index ed173573c8..b31212945b 100644 --- a/examples/skybox/main.rs +++ b/examples/skybox/main.rs @@ -261,7 +261,7 @@ impl framework::Example for Skybox { fn render( &mut self, - frame: &wgpu::SwapChainOutput, + frame: &wgpu::SwapChainTexture, device: &wgpu::Device, queue: &wgpu::Queue, ) -> wgpu::CommandBuffer { diff --git a/src/backend/direct.rs b/src/backend/direct.rs index 9c13fd0164..87670597dc 100644 --- a/src/backend/direct.rs +++ b/src/backend/direct.rs @@ -1,14 +1,14 @@ use crate::{ backend::native_gpu_future, BindGroupDescriptor, BindGroupLayoutDescriptor, BindingResource, BindingType, BufferDescriptor, CommandEncoderDescriptor, ComputePipelineDescriptor, - PipelineLayoutDescriptor, RenderPipelineDescriptor, SamplerDescriptor, TextureDescriptor, - TextureViewDescriptor, TextureViewDimension, + PipelineLayoutDescriptor, RenderPipelineDescriptor, SamplerDescriptor, SwapChainStatus, + TextureDescriptor, TextureViewDescriptor, TextureViewDimension, }; use arrayvec::ArrayVec; use futures::future::{ready, Ready}; use smallvec::SmallVec; -use std::{ffi::CString, marker::PhantomData, ptr, slice}; +use std::{ffi::CString, marker::PhantomData, ops::Range, ptr, slice}; macro_rules! gfx_select { ($id:expr => $global:ident.$method:ident( $($param:expr),+ )) => { @@ -89,7 +89,7 @@ mod pass_impl { &mut self, buffer: &wgc::id::BufferId, offset: wgt::BufferAddress, - size: wgt::BufferAddress, + size: wgt::BufferSize, ) { unsafe { wgpu_render_pass_set_index_buffer(self, *buffer, offset, size) } } @@ -98,7 +98,7 @@ mod pass_impl { slot: u32, buffer: &wgc::id::BufferId, offset: wgt::BufferAddress, - size: wgt::BufferAddress, + size: wgt::BufferSize, ) { unsafe { wgpu_render_pass_set_vertex_buffer(self, slot, *buffer, offset, size) } } @@ -358,7 +358,7 @@ impl crate::Context for Context { bm::BindingResource::Buffer(bm::BufferBinding { buffer: buffer_slice.buffer.id, offset: buffer_slice.offset, - size: buffer_slice.size_or_0(), + size: buffer_slice.size, }) } BindingResource::Sampler(ref sampler) => { @@ -590,10 +590,10 @@ impl crate::Context for Context { fn buffer_map_read( &self, buffer: &Self::BufferId, - start: wgt::BufferAddress, - size: wgt::BufferAddress, + range: Range, ) -> Self::MapReadFuture { - let (future, completion) = native_gpu_future::new_gpu_future(*buffer, size); + let (future, completion) = + native_gpu_future::new_gpu_future(*buffer, range.end - range.start); extern "C" fn buffer_map_read_future_wrapper( status: wgc::resource::BufferMapAsyncStatus, @@ -619,7 +619,7 @@ impl crate::Context for Context { callback: buffer_map_read_future_wrapper, userdata: completion.to_raw() as _, }; - gfx_select!(*buffer => self.buffer_map_async(*buffer, start .. start + size, operation)); + gfx_select!(*buffer => self.buffer_map_async(*buffer, range, operation)); future } @@ -627,10 +627,10 @@ impl crate::Context for Context { fn buffer_map_write( &self, buffer: &Self::BufferId, - start: wgt::BufferAddress, - size: wgt::BufferAddress, + range: Range, ) -> Self::MapWriteFuture { - let (future, completion) = native_gpu_future::new_gpu_future(*buffer, size); + let (future, completion) = + native_gpu_future::new_gpu_future(*buffer, range.end - range.start); extern "C" fn buffer_map_write_future_wrapper( status: wgc::resource::BufferMapAsyncStatus, @@ -656,7 +656,7 @@ impl crate::Context for Context { callback: buffer_map_write_future_wrapper, userdata: completion.to_raw() as _, }; - gfx_select!(*buffer => self.buffer_map_async(*buffer, start .. start + size, operation)); + gfx_select!(*buffer => self.buffer_map_async(*buffer, range, operation)); future } @@ -668,17 +668,11 @@ impl crate::Context for Context { fn swap_chain_get_next_texture( &self, swap_chain: &Self::SwapChainId, - ) -> Result<(Self::TextureViewId, Self::SwapChainOutputDetail), crate::TimeOut> { - gfx_select!(*swap_chain => self.swap_chain_get_next_texture(*swap_chain, PhantomData)) - .map(|output| { - ( - output.view_id.unwrap(), - SwapChainOutputDetail { - swap_chain_id: *swap_chain, - }, - ) - }) - .map_err(|_| crate::TimeOut) + ) -> (Option, SwapChainStatus, Self::SwapChainOutputDetail) { + let wgc::swap_chain::SwapChainOutput { status, view_id } = + gfx_select!(*swap_chain => self.swap_chain_get_next_texture(*swap_chain, PhantomData)); + + (view_id, status, SwapChainOutputDetail { swap_chain_id: *swap_chain }) } fn swap_chain_present(&self, view: &Self::TextureViewId, detail: &Self::SwapChainOutputDetail) { diff --git a/src/backend/web.rs b/src/backend/web.rs index 0f02ce3ba9..e0330a216c 100644 --- a/src/backend/web.rs +++ b/src/backend/web.rs @@ -1,8 +1,8 @@ use crate::{ BindGroupDescriptor, BindGroupLayoutDescriptor, BindingResource, BindingType, BufferDescriptor, CommandEncoderDescriptor, ComputePipelineDescriptor, PipelineLayoutDescriptor, - ProgrammableStageDescriptor, RenderPipelineDescriptor, SamplerDescriptor, TextureDescriptor, - TextureViewDescriptor, TextureViewDimension, + ProgrammableStageDescriptor, RenderPipelineDescriptor, SamplerDescriptor, SwapChainStatus, + TextureDescriptor, TextureViewDescriptor, TextureViewDimension, }; use futures::FutureExt; @@ -107,20 +107,22 @@ impl crate::RenderPassInner for RenderPass { &mut self, buffer: &Sendable, offset: wgt::BufferAddress, - size: wgt::BufferAddress, + size: wgt::BufferSize, ) { + assert_ne!(size, wgt::BufferSize::WHOLE); //TODO self.0 - .set_index_buffer_with_f64_and_f64(&buffer.0, offset as f64, size as f64); + .set_index_buffer_with_f64_and_f64(&buffer.0, offset as f64, size.0 as f64); } fn set_vertex_buffer( &mut self, slot: u32, buffer: &Sendable, offset: wgt::BufferAddress, - size: wgt::BufferAddress, + size: wgt::BufferSize, ) { + assert_ne!(size, wgt::BufferSize::WHOLE); //TODO self.0 - .set_vertex_buffer_with_f64_and_f64(slot, &buffer.0, offset as f64, size as f64); + .set_vertex_buffer_with_f64_and_f64(slot, &buffer.0, offset as f64, size.0 as f64); } fn set_blend_color(&mut self, color: wgt::Color) { self.0 @@ -830,7 +832,9 @@ impl crate::Context for Context { let mut mapped_buffer_binding = web_sys::GpuBufferBinding::new(&buffer_slice.buffer.id.0); mapped_buffer_binding.offset(buffer_slice.offset as f64); - mapped_buffer_binding.size(buffer_slice.size_or_0() as f64); + if buffer_slice.size != wgt::BufferSize::WHOLE { + mapped_buffer_binding.size(buffer_slice.size.0 as f64); + } JsValue::from(mapped_buffer_binding.clone()) } BindingResource::Sampler(ref sampler) => JsValue::from(sampler.id.0.clone()), @@ -1046,8 +1050,7 @@ impl crate::Context for Context { fn buffer_map_read( &self, buffer: &Self::BufferId, - _start: wgt::BufferAddress, - _size: wgt::BufferAddress, + _range: Range, ) -> Self::MapReadFuture { MakeSendFuture(MapFuture { child: wasm_bindgen_futures::JsFuture::from(buffer.0.map_read_async()), @@ -1059,8 +1062,7 @@ impl crate::Context for Context { fn buffer_map_write( &self, buffer: &Self::BufferId, - _start: wgt::BufferAddress, - _size: wgt::BufferAddress, + _range: Range, ) -> Self::MapWriteFuture { MakeSendFuture(MapFuture { child: wasm_bindgen_futures::JsFuture::from(buffer.0.map_write_async()), @@ -1076,13 +1078,10 @@ impl crate::Context for Context { fn swap_chain_get_next_texture( &self, swap_chain: &Self::SwapChainId, - ) -> Result<(Self::TextureViewId, Self::SwapChainOutputDetail), crate::TimeOut> { + ) -> (Option, SwapChainStatus, Self::SwapChainOutputDetail) { // TODO: Should we pass a descriptor here? // Or is the default view always correct? - Ok(( - Sendable(swap_chain.0.get_current_texture().create_view()), - (), - )) + (Some(Sendable(swap_chain.0.get_current_texture().create_view())), SwapChainStatus::Good, ()) } fn swap_chain_present( diff --git a/src/lib.rs b/src/lib.rs index 1ee757ff6c..25f0fd0a6f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,14 +18,14 @@ use std::{ pub use wgc::instance::{AdapterInfo, DeviceType}; pub use wgt::{ read_spirv, AddressMode, Backend, BackendBit, BlendDescriptor, BlendFactor, BlendOperation, - BufferAddress, BufferUsage, Color, ColorStateDescriptor, ColorWrite, CommandBufferDescriptor, - CompareFunction, CullMode, DepthStencilStateDescriptor, DeviceDescriptor, DynamicOffset, - Extensions, Extent3d, FilterMode, FrontFace, IndexFormat, InputStepMode, Limits, LoadOp, - Origin3d, PowerPreference, PresentMode, PrimitiveTopology, RasterizationStateDescriptor, - ShaderLocation, ShaderStage, StencilOperation, StencilStateFaceDescriptor, StoreOp, - SwapChainDescriptor, TextureAspect, TextureComponentType, TextureDataLayout, TextureDimension, - TextureFormat, TextureUsage, TextureViewDimension, VertexAttributeDescriptor, VertexFormat, - BIND_BUFFER_ALIGNMENT, MAX_BIND_GROUPS, + BufferAddress, BufferSize, BufferUsage, Color, ColorStateDescriptor, ColorWrite, + CommandBufferDescriptor, CompareFunction, CullMode, DepthStencilStateDescriptor, + DeviceDescriptor, DynamicOffset, Extensions, Extent3d, FilterMode, FrontFace, IndexFormat, + InputStepMode, Limits, LoadOp, Origin3d, PowerPreference, PresentMode, PrimitiveTopology, + RasterizationStateDescriptor, ShaderLocation, ShaderStage, StencilOperation, + StencilStateFaceDescriptor, StoreOp, SwapChainDescriptor, SwapChainStatus, TextureAspect, + TextureComponentType, TextureDataLayout, TextureDimension, TextureFormat, TextureUsage, + TextureViewDimension, VertexAttributeDescriptor, VertexFormat, BIND_BUFFER_ALIGNMENT, }; use backend::Context as C; @@ -54,18 +54,13 @@ trait RenderPassInner { bind_group: &Ctx::BindGroupId, offsets: &[DynamicOffset], ); - fn set_index_buffer( - &mut self, - buffer: &Ctx::BufferId, - offset: BufferAddress, - size: BufferAddress, - ); + fn set_index_buffer(&mut self, buffer: &Ctx::BufferId, offset: BufferAddress, size: BufferSize); fn set_vertex_buffer( &mut self, slot: u32, buffer: &Ctx::BufferId, offset: BufferAddress, - size: BufferAddress, + size: BufferSize, ); fn set_blend_color(&mut self, color: wgt::Color); fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32); @@ -207,20 +202,18 @@ trait Context: Sized { fn buffer_map_read( &self, buffer: &Self::BufferId, - start: BufferAddress, - size: BufferAddress, + range: Range, ) -> Self::MapReadFuture; fn buffer_map_write( &self, buffer: &Self::BufferId, - start: BufferAddress, - size: BufferAddress, + range: Range, ) -> Self::MapWriteFuture; fn buffer_unmap(&self, buffer: &Self::BufferId); fn swap_chain_get_next_texture( &self, swap_chain: &Self::SwapChainId, - ) -> Result<(Self::TextureViewId, Self::SwapChainOutputDetail), TimeOut>; + ) -> (Option, SwapChainStatus, Self::SwapChainOutputDetail); fn swap_chain_present(&self, view: &Self::TextureViewId, detail: &Self::SwapChainOutputDetail); fn texture_create_view( &self, @@ -357,22 +350,14 @@ pub enum Maintain { pub struct Buffer { context: Arc, id: ::BufferId, - //detail: ::BufferDetail, + size: BufferAddress, } /// A description of what portion of a buffer to use pub struct BufferSlice<'a> { buffer: &'a Buffer, offset: BufferAddress, - size: Option, -} - -impl<'a> BufferSlice<'a> { - /// This fn can be used for calling lower-level APIs where `0` denotes that the slice should - /// extend to the end of the buffer. - fn size_or_0(&self) -> BufferAddress { - self.size.unwrap_or(0) - } + size: BufferSize, } /// A handle to a texture on the GPU. @@ -835,11 +820,26 @@ pub type TextureViewDescriptor<'a> = wgt::TextureViewDescriptor> pub type SamplerDescriptor<'a> = wgt::SamplerDescriptor>; /// A swap chain image that can be rendered to. -pub struct SwapChainOutput { +pub struct SwapChainTexture { pub view: TextureView, detail: ::SwapChainOutputDetail, } +/// The result of a successful call to `SwapChain::get_next_frame`. +pub struct SwapChainFrame { + pub output: SwapChainTexture, + pub suboptimal: bool, +} + +/// The result of an unsuccessful call to `SwapChain::get_next_frame`. +#[derive(Debug)] +pub enum SwapChainError { + Timeout, + Outdated, + Lost, + OutOfMemory, +} + /// A view of a buffer which can be used to copy to or from a texture. #[derive(Clone)] pub struct BufferCopyView<'a> { @@ -887,7 +887,7 @@ impl CreateBufferMapped<'_> { Buffer { context: self.context, id: self.id, - //detail: self.detail, + size: self.mapped_data.len() as BufferAddress, } } } @@ -1074,6 +1074,7 @@ impl Device { Buffer { context: Arc::clone(&self.context), id: Context::device_create_buffer(&*self.context, &self.id, desc), + size: desc.size, } } @@ -1197,9 +1198,9 @@ impl Buffer { Bound::Unbounded => 0, }; let size = match bounds.end_bound() { - Bound::Included(&bound) => Some(bound + 1 - offset), - Bound::Excluded(&bound) => Some(bound - offset), - Bound::Unbounded => None, + Bound::Included(&bound) => BufferSize(bound + 1 - offset), + Bound::Excluded(&bound) => BufferSize(bound - offset), + Bound::Unbounded => BufferSize::WHOLE, }; BufferSlice { buffer: self, @@ -1219,11 +1220,16 @@ impl Buffer { pub fn map_read( &self, start: BufferAddress, - size: BufferAddress, + size: BufferSize, ) -> impl Future> + Send { let context = Arc::clone(&self.context); + let end = if size == BufferSize::WHOLE { + self.size + } else { + start + size.0 + }; self.context - .buffer_map_read(&self.id, start, size) + .buffer_map_read(&self.id, start..end) .map(|result| result.map(|detail| BufferReadMapping { context, detail })) } @@ -1234,11 +1240,16 @@ impl Buffer { pub fn map_write( &self, start: BufferAddress, - size: BufferAddress, + size: BufferSize, ) -> impl Future> + Send { let context = Arc::clone(&self.context); + let end = if size == BufferSize::WHOLE { + self.size + } else { + start + size.0 + }; self.context - .buffer_map_write(&self.id, start, size) + .buffer_map_write(&self.id, start..end) .map(|result| result.map(|detail| BufferWriteMapping { context, detail })) } @@ -1422,7 +1433,7 @@ impl<'a> RenderPass<'a> { &mut self.id, &buffer_slice.buffer.id, buffer_slice.offset, - buffer_slice.size_or_0(), + buffer_slice.size, ) } @@ -1444,7 +1455,7 @@ impl<'a> RenderPass<'a> { slot, &buffer_slice.buffer.id, buffer_slice.offset, - buffer_slice.size_or_0(), + buffer_slice.size, ) } @@ -1613,7 +1624,7 @@ impl Queue { } } -impl Drop for SwapChainOutput { +impl Drop for SwapChainTexture { fn drop(&mut self) { if !thread::panicking() { Context::swap_chain_present(&*self.view.context, &self.view.id, &self.detail); @@ -1621,26 +1632,36 @@ impl Drop for SwapChainOutput { } } -/// The GPU timed out when attempting to acquire the next texture or if a -/// previous output is still alive. -#[derive(Clone, Debug)] -pub struct TimeOut; - impl SwapChain { /// Returns the next texture to be presented by the swapchain for drawing. /// /// When the [`SwapChainOutput`] returned by this method is dropped, the swapchain will present /// the texture to the associated [`Surface`]. - pub fn get_next_texture(&mut self) -> Result { - Context::swap_chain_get_next_texture(&*self.context, &self.id).map(|(id, detail)| { - SwapChainOutput { - view: TextureView { - context: Arc::clone(&self.context), - id, - owned: false, - }, - detail, - } - }) + pub fn get_next_frame(&mut self) -> Result { + let (view_id, status, detail) = + Context::swap_chain_get_next_texture(&*self.context, &self.id); + let output = view_id.map(|id| SwapChainTexture { + view: TextureView { + context: Arc::clone(&self.context), + id: id, + owned: false, + }, + detail, + }); + + match status { + SwapChainStatus::Good => Ok(SwapChainFrame { + output: output.unwrap(), + suboptimal: false, + }), + SwapChainStatus::Suboptimal => Ok(SwapChainFrame { + output: output.unwrap(), + suboptimal: true, + }), + SwapChainStatus::Timeout => Err(SwapChainError::Timeout), + SwapChainStatus::Outdated => Err(SwapChainError::Outdated), + SwapChainStatus::Lost => Err(SwapChainError::Lost), + SwapChainStatus::OutOfMemory => Err(SwapChainError::OutOfMemory), + } } }