mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 14:55:05 +00:00
Merge swap chain into surface
This commit is contained in:
parent
3afab9c5aa
commit
f78061bcef
@ -8,6 +8,7 @@
|
||||
- processing SPIR-V inputs for later translation now requires `spirv` compile feature enabled
|
||||
- new `Features::SPIRV_SHADER_PASSTHROUGH` run-time feature allows providing pass-through SPIR-V (orthogonal to the compile feature)
|
||||
- several bitflag names are renamed to plural: `TextureUsage`, `BufferUsage`, `ColorWrite`.
|
||||
- the `SwapChain` is merged into `Surface`.
|
||||
- renamed `TextureUsage` bits: `SAMPLED` -> `TEXTURE_BINDING`, `STORAGE` -> `STORAGE_BINDING`.
|
||||
- renamed `InputStepMode` to `VertexStepMode`
|
||||
- Implemented `Rgb9e5Ufloat` format.
|
||||
|
@ -103,7 +103,7 @@ fn main() {
|
||||
event_loop::ControlFlow,
|
||||
};
|
||||
|
||||
let mut resize_desc = None;
|
||||
let mut resize_config = None;
|
||||
let mut frame_count = 0;
|
||||
let mut done = false;
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
@ -112,31 +112,30 @@ fn main() {
|
||||
Event::MainEventsCleared => {
|
||||
window.request_redraw();
|
||||
}
|
||||
Event::RedrawRequested(_) if resize_desc.is_none() => loop {
|
||||
Event::RedrawRequested(_) if resize_config.is_none() => loop {
|
||||
match actions.pop() {
|
||||
Some(trace::Action::CreateSwapChain(id, desc)) => {
|
||||
log::info!("Initializing the swapchain");
|
||||
assert_eq!(id.to_surface_id(), surface);
|
||||
Some(trace::Action::ConfigureSurface(_device_id, config)) => {
|
||||
log::info!("Configuring the surface");
|
||||
let current_size: (u32, u32) = window.inner_size().into();
|
||||
let size = (desc.width, desc.height);
|
||||
let size = (config.width, config.height);
|
||||
if current_size != size {
|
||||
window.set_inner_size(winit::dpi::PhysicalSize::new(
|
||||
desc.width,
|
||||
desc.height,
|
||||
config.width,
|
||||
config.height,
|
||||
));
|
||||
resize_desc = Some(desc);
|
||||
resize_config = Some(config);
|
||||
break;
|
||||
} else {
|
||||
let (_, error) = gfx_select!(device => global.device_create_swap_chain(device, surface, &desc));
|
||||
let error = gfx_select!(device => global.surface_configure(surface, device, &config));
|
||||
if let Some(e) = error {
|
||||
panic!("{:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(trace::Action::PresentSwapChain(id)) => {
|
||||
Some(trace::Action::Present(id)) => {
|
||||
frame_count += 1;
|
||||
log::debug!("Presenting frame {}", frame_count);
|
||||
gfx_select!(device => global.swap_chain_present(id)).unwrap();
|
||||
gfx_select!(device => global.surface_present(id)).unwrap();
|
||||
break;
|
||||
}
|
||||
Some(action) => {
|
||||
@ -153,8 +152,8 @@ fn main() {
|
||||
},
|
||||
Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::Resized(_) => {
|
||||
if let Some(desc) = resize_desc.take() {
|
||||
let (_, error) = gfx_select!(device => global.device_create_swap_chain(device, surface, &desc));
|
||||
if let Some(config) = resize_config.take() {
|
||||
let error = gfx_select!(device => global.surface_configure(surface, device, &config));
|
||||
if let Some(e) = error {
|
||||
panic!("{:?}", e);
|
||||
}
|
||||
|
@ -149,8 +149,8 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
|
||||
Action::Init { .. } => {
|
||||
panic!("Unexpected Action::Init: has to be the first action only")
|
||||
}
|
||||
Action::CreateSwapChain { .. } | Action::PresentSwapChain(_) => {
|
||||
panic!("Unexpected SwapChain action: winit feature is not enabled")
|
||||
Action::ConfigureSurface { .. } | Action::Present(_) => {
|
||||
panic!("Unexpected Surface action: winit feature is not enabled")
|
||||
}
|
||||
Action::CreateBuffer(id, desc) => {
|
||||
self.device_maintain_ids::<A>(device).unwrap();
|
||||
@ -202,9 +202,9 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
|
||||
Action::DestroySampler(id) => {
|
||||
self.sampler_drop::<A>(id);
|
||||
}
|
||||
Action::GetSwapChainTexture { id, parent_id } => {
|
||||
Action::GetSurfaceTexture { id, parent_id } => {
|
||||
self.device_maintain_ids::<A>(device).unwrap();
|
||||
self.swap_chain_get_current_texture_view::<A>(parent_id, id)
|
||||
self.surface_get_current_texture_view::<A>(parent_id, id)
|
||||
.unwrap()
|
||||
.view_id
|
||||
.unwrap();
|
||||
|
@ -91,8 +91,8 @@ pub enum CreateBindGroupError {
|
||||
MissingTextureUsage(#[from] MissingTextureUsageError),
|
||||
#[error("binding declared as a single item, but bind group is using it as an array")]
|
||||
SingleBindingExpected,
|
||||
#[error("unable to create a bind group with a swap chain image")]
|
||||
SwapChainImage,
|
||||
#[error("unable to create a bind group with a surface image")]
|
||||
SurfaceImage,
|
||||
#[error("buffer offset {0} does not respect `BIND_BUFFER_ALIGNMENT`")]
|
||||
UnalignedBufferOffset(wgt::BufferAddress),
|
||||
#[error(
|
||||
|
@ -141,7 +141,7 @@ pub struct CommandBuffer<A: hal::Api> {
|
||||
status: CommandEncoderStatus,
|
||||
pub(crate) device_id: Stored<id::DeviceId>,
|
||||
pub(crate) trackers: TrackerSet,
|
||||
pub(crate) used_swap_chains: SmallVec<[Stored<id::SwapChainId>; 1]>,
|
||||
pub(crate) used_surfaces: SmallVec<[id::Valid<id::SurfaceId>; 1]>,
|
||||
buffer_memory_init_actions: Vec<MemoryInitTrackerAction<id::BufferId>>,
|
||||
limits: wgt::Limits,
|
||||
support_fill_buffer_texture: bool,
|
||||
@ -169,7 +169,7 @@ impl<A: HalApi> CommandBuffer<A> {
|
||||
status: CommandEncoderStatus::Recording,
|
||||
device_id,
|
||||
trackers: TrackerSet::new(A::VARIANT),
|
||||
used_swap_chains: Default::default(),
|
||||
used_surfaces: Default::default(),
|
||||
buffer_memory_init_actions: Default::default(),
|
||||
limits,
|
||||
support_fill_buffer_texture: features.contains(wgt::Features::CLEAR_COMMANDS),
|
||||
|
@ -13,10 +13,10 @@ use crate::{
|
||||
error::{ErrorFormatter, PrettyError},
|
||||
hub::{Global, GlobalIdentityHandlerFactory, HalApi, Storage, Token},
|
||||
id,
|
||||
instance::Surface,
|
||||
memory_init_tracker::{MemoryInitKind, MemoryInitTrackerAction},
|
||||
pipeline::PipelineFlags,
|
||||
resource::{Texture, TextureView, TextureViewSource},
|
||||
swap_chain::SwapChain,
|
||||
track::{StatefulTrackerSubset, TextureSelector, UsageConflict},
|
||||
validation::{
|
||||
check_buffer_usage, check_texture_usage, MissingBufferUsageError, MissingTextureUsageError,
|
||||
@ -414,8 +414,6 @@ pub enum RenderPassErrorInner {
|
||||
InvalidResolveTargetSampleCount,
|
||||
#[error("not enough memory left")]
|
||||
OutOfMemory,
|
||||
#[error("attempted to use a swap chain image as a depth/stencil attachment")]
|
||||
SwapChainImageAsDepthStencil,
|
||||
#[error("unable to clear non-present/read-only depth")]
|
||||
InvalidDepthOps,
|
||||
#[error("unable to clear non-present/read-only stencil")]
|
||||
@ -522,7 +520,7 @@ struct RenderPassInfo<'a, A: hal::Api> {
|
||||
context: RenderPassContext,
|
||||
trackers: StatefulTrackerSubset,
|
||||
render_attachments: AttachmentDataVec<RenderAttachment<'a>>,
|
||||
used_swap_chain: Option<Stored<id::SwapChainId>>,
|
||||
used_surface: Option<id::Valid<id::SurfaceId>>,
|
||||
is_ds_read_only: bool,
|
||||
extent: wgt::Extent3d,
|
||||
_phantom: PhantomData<A>,
|
||||
@ -535,7 +533,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
||||
depth_stencil_attachment: Option<&RenderPassDepthStencilAttachment>,
|
||||
cmd_buf: &mut CommandBuffer<A>,
|
||||
view_guard: &'a Storage<TextureView<A>, id::TextureViewId>,
|
||||
swap_chain_guard: &'a Storage<SwapChain<A>, id::SwapChainId>,
|
||||
surface_guard: &'a Storage<Surface, id::SurfaceId>,
|
||||
) -> Result<Self, RenderPassErrorInner> {
|
||||
profiling::scope!("start", "RenderPassInfo");
|
||||
|
||||
@ -549,7 +547,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
||||
let mut attachment_type_name = "";
|
||||
let mut extent = None;
|
||||
let mut sample_count = 0;
|
||||
let mut used_swap_chain = None::<(Stored<id::SwapChainId>, hal::TextureUses)>;
|
||||
let mut used_surface = None::<(id::Valid<id::SurfaceId>, hal::TextureUses)>;
|
||||
|
||||
let mut add_view = |view: &TextureView<A>, type_name| {
|
||||
if let Some(ex) = extent {
|
||||
@ -594,9 +592,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
||||
|
||||
let source_id = match view.source {
|
||||
TextureViewSource::Native(ref source_id) => source_id,
|
||||
TextureViewSource::SwapChain(_) => {
|
||||
return Err(RenderPassErrorInner::SwapChainImageAsDepthStencil);
|
||||
}
|
||||
TextureViewSource::Surface(_) => unreachable!(),
|
||||
};
|
||||
|
||||
let usage = if at.is_read_only(ds_aspects)? {
|
||||
@ -648,14 +644,14 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
||||
usage: hal::TextureUses::COLOR_TARGET,
|
||||
});
|
||||
}
|
||||
TextureViewSource::SwapChain(ref source_id) => {
|
||||
TextureViewSource::Surface(source_id) => {
|
||||
//HACK: guess the start usage based on the load op
|
||||
let start_usage = match at.channel.load_op {
|
||||
LoadOp::Load => hal::TextureUses::empty(),
|
||||
LoadOp::Clear => hal::TextureUses::UNINITIALIZED,
|
||||
};
|
||||
assert!(used_swap_chain.is_none());
|
||||
used_swap_chain = Some((source_id.clone(), start_usage));
|
||||
assert!(used_surface.is_none());
|
||||
used_surface = Some((source_id, start_usage));
|
||||
}
|
||||
};
|
||||
|
||||
@ -687,11 +683,11 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
||||
usage: hal::TextureUses::COLOR_TARGET,
|
||||
});
|
||||
}
|
||||
TextureViewSource::SwapChain(ref source_id) => {
|
||||
TextureViewSource::Surface(source_id) => {
|
||||
//HACK: guess the start usage
|
||||
let start_usage = hal::TextureUses::UNINITIALIZED;
|
||||
assert!(used_swap_chain.is_none());
|
||||
used_swap_chain = Some((source_id.clone(), start_usage));
|
||||
assert!(used_surface.is_none());
|
||||
used_surface = Some((source_id, start_usage));
|
||||
}
|
||||
};
|
||||
|
||||
@ -716,8 +712,8 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
||||
return Err(RenderPassErrorInner::InvalidSampleCount(sample_count));
|
||||
}
|
||||
|
||||
if let Some((ref sc_id, start_usage)) = used_swap_chain {
|
||||
let &(_, ref suf_texture) = swap_chain_guard[sc_id.value]
|
||||
if let Some((surface_id, start_usage)) = used_surface {
|
||||
let suf_texture = A::get_surface(&surface_guard[surface_id])
|
||||
.acquired_texture
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
@ -764,7 +760,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
||||
context,
|
||||
trackers: StatefulTrackerSubset::new(A::VARIANT),
|
||||
render_attachments,
|
||||
used_swap_chain: used_swap_chain.map(|(sc_id, _)| sc_id),
|
||||
used_surface: used_surface.map(|(sc_id, _)| sc_id),
|
||||
is_ds_read_only,
|
||||
extent,
|
||||
_phantom: PhantomData,
|
||||
@ -775,19 +771,17 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
||||
mut self,
|
||||
raw: &mut A::CommandEncoder,
|
||||
texture_guard: &Storage<Texture<A>, id::TextureId>,
|
||||
swap_chain_guard: &Storage<SwapChain<A>, id::SwapChainId>,
|
||||
) -> Result<(StatefulTrackerSubset, Option<Stored<id::SwapChainId>>), RenderPassErrorInner>
|
||||
surface_guard: &Storage<Surface, id::SurfaceId>,
|
||||
) -> Result<(StatefulTrackerSubset, Option<id::Valid<id::SurfaceId>>), RenderPassErrorInner>
|
||||
{
|
||||
profiling::scope!("finish", "RenderPassInfo");
|
||||
unsafe {
|
||||
raw.end_render_pass();
|
||||
}
|
||||
|
||||
if let Some(ref sc_id) = self.used_swap_chain {
|
||||
let &(_, ref suf_texture) = swap_chain_guard[sc_id.value]
|
||||
.acquired_texture
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
if let Some(surface_id) = self.used_surface {
|
||||
let suf = A::get_surface(&surface_guard[surface_id]);
|
||||
let suf_texture = suf.acquired_texture.as_ref().unwrap();
|
||||
let barrier = hal::TextureBarrier {
|
||||
texture: std::borrow::Borrow::borrow(suf_texture),
|
||||
usage: hal::TextureUses::COLOR_TARGET..hal::TextureUses::empty(),
|
||||
@ -814,7 +808,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
|
||||
.map_err(UsageConflict::from)?;
|
||||
}
|
||||
|
||||
Ok((self.trackers, self.used_swap_chain))
|
||||
Ok((self.trackers, self.used_surface))
|
||||
}
|
||||
}
|
||||
|
||||
@ -848,10 +842,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
let hub = A::hub(self);
|
||||
let mut token = Token::root();
|
||||
|
||||
let (surface_guard, mut token) = self.surfaces.read(&mut token);
|
||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||
|
||||
let (pass_raw, trackers, query_reset_state) = {
|
||||
let (swap_chain_guard, mut token) = hub.swap_chains.read(&mut token);
|
||||
let (mut cmb_guard, mut token) = hub.command_buffers.write(&mut token);
|
||||
|
||||
let cmd_buf =
|
||||
@ -895,7 +889,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
depth_stencil_attachment,
|
||||
cmd_buf,
|
||||
&*view_guard,
|
||||
&*swap_chain_guard,
|
||||
&*surface_guard,
|
||||
)
|
||||
.map_pass_err(scope)?;
|
||||
|
||||
@ -1762,8 +1756,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
}
|
||||
|
||||
log::trace!("Merging {:?} with the render pass", encoder_id);
|
||||
let (trackers, used_swapchain) = info
|
||||
.finish(raw, &*texture_guard, &*swap_chain_guard)
|
||||
let (trackers, used_surface) = info
|
||||
.finish(raw, &*texture_guard, &*surface_guard)
|
||||
.map_pass_err(scope)?;
|
||||
|
||||
let raw_cmd_buf = unsafe {
|
||||
@ -1772,7 +1766,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.map_pass_err(scope)?
|
||||
};
|
||||
cmd_buf.status = CommandEncoderStatus::Recording;
|
||||
cmd_buf.used_swap_chains.extend(used_swapchain);
|
||||
cmd_buf.used_surfaces.extend(used_surface);
|
||||
(raw_cmd_buf, trackers, query_reset_state)
|
||||
};
|
||||
|
||||
|
@ -391,7 +391,7 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
resource::TextureViewSource::Native(ref source_id) => {
|
||||
self.suspected_resources.textures.push(source_id.value);
|
||||
}
|
||||
resource::TextureViewSource::SwapChain { .. } => {}
|
||||
resource::TextureViewSource::Surface { .. } => {}
|
||||
};
|
||||
self.schedule_texture_view_for_destruction(id, res);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use crate::{
|
||||
hub::{Global, GlobalIdentityHandlerFactory, HalApi, Hub, Input, InvalidId, Storage, Token},
|
||||
id, instance,
|
||||
memory_init_tracker::{MemoryInitKind, MemoryInitTracker, MemoryInitTrackerAction},
|
||||
pipeline, resource, swap_chain,
|
||||
pipeline, present, resource,
|
||||
track::{BufferState, TextureSelector, TextureState, TrackerSet, UsageConflict},
|
||||
validation::{self, check_buffer_usage, check_texture_usage},
|
||||
FastHashMap, Label, LabelHelpers as _, LifeGuard, MultiRefCount, Stored, SubmissionIndex,
|
||||
@ -1448,8 +1448,8 @@ impl<A: HalApi> Device<A> {
|
||||
.map_err(UsageConflict::from)?;
|
||||
check_texture_usage(texture.desc.usage, pub_usage)?;
|
||||
}
|
||||
resource::TextureViewSource::SwapChain(_) => {
|
||||
return Err(Error::SwapChainImage);
|
||||
resource::TextureViewSource::Surface(_) => {
|
||||
return Err(Error::SurfaceImage);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1500,8 +1500,8 @@ impl<A: HalApi> Device<A> {
|
||||
.map_err(UsageConflict::from)?;
|
||||
check_texture_usage(texture.desc.usage, pub_usage)?;
|
||||
}
|
||||
resource::TextureViewSource::SwapChain(_) => {
|
||||
return Err(Error::SwapChainImage);
|
||||
resource::TextureViewSource::Surface(_) => {
|
||||
return Err(Error::SurfaceImage);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2478,6 +2478,10 @@ impl<A: hal::Api> Device<A> {
|
||||
}
|
||||
life_tracker.triage_submissions(current_index, &self.command_allocator);
|
||||
life_tracker.cleanup(&self.raw);
|
||||
#[cfg(feature = "trace")]
|
||||
{
|
||||
self.trace = None;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn dispose(self) {
|
||||
@ -2567,34 +2571,34 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
let hub = A::hub(self);
|
||||
let mut token = Token::root();
|
||||
|
||||
let (mut surface_guard, mut token) = self.surfaces.write(&mut token);
|
||||
let (surface_guard, mut token) = self.surfaces.read(&mut token);
|
||||
let (adapter_guard, mut _token) = hub.adapters.read(&mut token);
|
||||
let adapter = adapter_guard
|
||||
.get(adapter_id)
|
||||
.map_err(|_| instance::IsSurfaceSupportedError::InvalidAdapter)?;
|
||||
let surface = surface_guard
|
||||
.get_mut(surface_id)
|
||||
.get(surface_id)
|
||||
.map_err(|_| instance::IsSurfaceSupportedError::InvalidSurface)?;
|
||||
Ok(adapter.is_surface_supported(surface))
|
||||
}
|
||||
pub fn adapter_get_swap_chain_preferred_format<A: HalApi>(
|
||||
pub fn surface_get_preferred_format<A: HalApi>(
|
||||
&self,
|
||||
adapter_id: id::AdapterId,
|
||||
surface_id: id::SurfaceId,
|
||||
) -> Result<TextureFormat, instance::GetSwapChainPreferredFormatError> {
|
||||
adapter_id: id::AdapterId,
|
||||
) -> Result<TextureFormat, instance::GetSurfacePreferredFormatError> {
|
||||
let hub = A::hub(self);
|
||||
let mut token = Token::root();
|
||||
|
||||
let (mut surface_guard, mut token) = self.surfaces.write(&mut token);
|
||||
let (surface_guard, mut token) = self.surfaces.read(&mut token);
|
||||
let (adapter_guard, mut _token) = hub.adapters.read(&mut token);
|
||||
let adapter = adapter_guard
|
||||
.get(adapter_id)
|
||||
.map_err(|_| instance::GetSwapChainPreferredFormatError::InvalidAdapter)?;
|
||||
.map_err(|_| instance::GetSurfacePreferredFormatError::InvalidAdapter)?;
|
||||
let surface = surface_guard
|
||||
.get_mut(surface_id)
|
||||
.map_err(|_| instance::GetSwapChainPreferredFormatError::InvalidSurface)?;
|
||||
.get(surface_id)
|
||||
.map_err(|_| instance::GetSurfacePreferredFormatError::InvalidSurface)?;
|
||||
|
||||
adapter.get_swap_chain_preferred_format(surface)
|
||||
surface.get_preferred_format(adapter)
|
||||
}
|
||||
|
||||
pub fn device_features<A: HalApi>(
|
||||
@ -3260,8 +3264,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
resource::TextureViewSource::Native(ref source_id) => {
|
||||
texture_guard[source_id.value].device_id.value
|
||||
}
|
||||
resource::TextureViewSource::SwapChain(_) => {
|
||||
return Err(resource::TextureViewDestroyError::SwapChainImage)
|
||||
resource::TextureViewSource::Surface(_) => {
|
||||
return Err(resource::TextureViewDestroyError::SurfaceImage)
|
||||
}
|
||||
};
|
||||
(last_submit_index, device_id)
|
||||
@ -4289,19 +4293,20 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.push(layout_id);
|
||||
}
|
||||
|
||||
pub fn device_create_swap_chain<A: HalApi>(
|
||||
pub fn surface_configure<A: HalApi>(
|
||||
&self,
|
||||
device_id: id::DeviceId,
|
||||
surface_id: id::SurfaceId,
|
||||
desc: &wgt::SwapChainDescriptor,
|
||||
) -> (id::SwapChainId, Option<swap_chain::CreateSwapChainError>) {
|
||||
device_id: id::DeviceId,
|
||||
config: &wgt::SurfaceConfiguration,
|
||||
) -> Option<present::ConfigureSurfaceError> {
|
||||
use hal::{Adapter as _, Surface as _};
|
||||
profiling::scope!("create_swap_chain", "Device");
|
||||
use present::ConfigureSurfaceError as E;
|
||||
profiling::scope!("surface_configure");
|
||||
|
||||
fn validate_swap_chain_descriptor(
|
||||
fn validate_surface_configuraiton(
|
||||
config: &mut hal::SurfaceConfiguration,
|
||||
caps: &hal::SurfaceCapabilities,
|
||||
) -> Result<(), swap_chain::CreateSwapChainError> {
|
||||
) -> Result<(), E> {
|
||||
let width = config.extent.width;
|
||||
let height = config.extent.height;
|
||||
if width < caps.extents.start().width
|
||||
@ -4324,29 +4329,27 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
config.present_mode = wgt::PresentMode::Fifo;
|
||||
}
|
||||
if !caps.formats.contains(&config.format) {
|
||||
return Err(swap_chain::CreateSwapChainError::UnsupportedFormat {
|
||||
return Err(E::UnsupportedFormat {
|
||||
requested: config.format,
|
||||
available: caps.formats.clone(),
|
||||
});
|
||||
}
|
||||
if !caps.usage.contains(config.usage) {
|
||||
return Err(swap_chain::CreateSwapChainError::UnsupportedUsage);
|
||||
return Err(E::UnsupportedUsage);
|
||||
}
|
||||
if width == 0 || height == 0 {
|
||||
return Err(swap_chain::CreateSwapChainError::ZeroArea);
|
||||
return Err(E::ZeroArea);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
log::info!("creating swap chain {:?}", desc);
|
||||
let sc_id = surface_id.to_swap_chain_id(A::VARIANT);
|
||||
log::info!("configuring surface with {:?}", config);
|
||||
let hub = A::hub(self);
|
||||
let mut token = Token::root();
|
||||
|
||||
let (mut surface_guard, mut token) = self.surfaces.write(&mut token);
|
||||
let (adapter_guard, mut token) = hub.adapters.read(&mut token);
|
||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||
let (mut swap_chain_guard, _) = hub.swap_chains.write(&mut token);
|
||||
let (device_guard, _token) = hub.devices.read(&mut token);
|
||||
|
||||
let error = loop {
|
||||
let device = match device_guard.get(device_id) {
|
||||
@ -4357,86 +4360,82 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
if let Some(ref trace) = device.trace {
|
||||
trace
|
||||
.lock()
|
||||
.add(trace::Action::CreateSwapChain(sc_id, desc.clone()));
|
||||
.add(trace::Action::ConfigureSurface(surface_id, config.clone()));
|
||||
}
|
||||
|
||||
let surface = match surface_guard.get_mut(surface_id) {
|
||||
Ok(surface) => surface,
|
||||
Err(_) => break swap_chain::CreateSwapChainError::InvalidSurface,
|
||||
Err(_) => break E::InvalidSurface,
|
||||
};
|
||||
|
||||
let caps = unsafe {
|
||||
let surface = A::get_surface_mut(surface);
|
||||
let suf = A::get_surface(surface);
|
||||
let adapter = &adapter_guard[device.adapter_id.value];
|
||||
match adapter.raw.adapter.surface_capabilities(surface) {
|
||||
match adapter.raw.adapter.surface_capabilities(&suf.raw) {
|
||||
Some(caps) => caps,
|
||||
None => break swap_chain::CreateSwapChainError::UnsupportedQueueFamily,
|
||||
None => break E::UnsupportedQueueFamily,
|
||||
}
|
||||
};
|
||||
|
||||
let num_frames = swap_chain::DESIRED_NUM_FRAMES
|
||||
let num_frames = present::DESIRED_NUM_FRAMES
|
||||
.max(*caps.swap_chain_sizes.start())
|
||||
.min(*caps.swap_chain_sizes.end());
|
||||
let mut config = hal::SurfaceConfiguration {
|
||||
let mut hal_config = hal::SurfaceConfiguration {
|
||||
swap_chain_size: num_frames,
|
||||
present_mode: desc.present_mode,
|
||||
present_mode: config.present_mode,
|
||||
composite_alpha_mode: hal::CompositeAlphaMode::Opaque,
|
||||
format: desc.format,
|
||||
format: config.format,
|
||||
extent: wgt::Extent3d {
|
||||
width: desc.width,
|
||||
height: desc.height,
|
||||
width: config.width,
|
||||
height: config.height,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
usage: conv::map_texture_usage(desc.usage, hal::FormatAspects::COLOR),
|
||||
usage: conv::map_texture_usage(config.usage, hal::FormatAspects::COLOR),
|
||||
};
|
||||
|
||||
if let Err(error) = validate_swap_chain_descriptor(&mut config, &caps) {
|
||||
if let Err(error) = validate_surface_configuraiton(&mut hal_config, &caps) {
|
||||
break error;
|
||||
}
|
||||
|
||||
match unsafe { A::get_surface_mut(surface).configure(&device.raw, &config) } {
|
||||
match unsafe {
|
||||
A::get_surface_mut(surface)
|
||||
.raw
|
||||
.configure(&device.raw, &hal_config)
|
||||
} {
|
||||
Ok(()) => (),
|
||||
Err(error) => {
|
||||
break match error {
|
||||
hal::SurfaceError::Outdated | hal::SurfaceError::Lost => {
|
||||
swap_chain::CreateSwapChainError::InvalidSurface
|
||||
}
|
||||
hal::SurfaceError::Device(error) => {
|
||||
swap_chain::CreateSwapChainError::Device(error.into())
|
||||
}
|
||||
hal::SurfaceError::Outdated | hal::SurfaceError::Lost => E::InvalidSurface,
|
||||
hal::SurfaceError::Device(error) => E::Device(error.into()),
|
||||
hal::SurfaceError::Other(message) => {
|
||||
log::error!("surface configuration failed: {}", message);
|
||||
swap_chain::CreateSwapChainError::InvalidSurface
|
||||
E::InvalidSurface
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(sc) = swap_chain_guard.try_remove(sc_id) {
|
||||
if sc.acquired_texture.is_some() {
|
||||
break swap_chain::CreateSwapChainError::SwapChainOutputExists;
|
||||
if let Some(present) = surface.presentation.take() {
|
||||
if present.acquired_texture.is_some() {
|
||||
break E::PreviousOutputExists;
|
||||
}
|
||||
}
|
||||
|
||||
let swap_chain = swap_chain::SwapChain {
|
||||
life_guard: LifeGuard::new("<SwapChain>"),
|
||||
surface.presentation = Some(present::Presentation {
|
||||
device_id: Stored {
|
||||
value: id::Valid(device_id),
|
||||
ref_count: device.life_guard.add_ref(),
|
||||
},
|
||||
desc: desc.clone(),
|
||||
config: config.clone(),
|
||||
num_frames,
|
||||
acquired_texture: None,
|
||||
active_submission_index: 0,
|
||||
marker: PhantomData,
|
||||
};
|
||||
swap_chain_guard.insert(sc_id, swap_chain);
|
||||
});
|
||||
|
||||
return (sc_id, None);
|
||||
return None;
|
||||
};
|
||||
|
||||
swap_chain_guard.insert_error(sc_id, "");
|
||||
(sc_id, Some(error))
|
||||
Some(error)
|
||||
}
|
||||
|
||||
#[cfg(feature = "replay")]
|
||||
|
@ -15,7 +15,6 @@ use crate::{
|
||||
|
||||
use hal::{CommandEncoder as _, Device as _, Queue as _};
|
||||
use parking_lot::Mutex;
|
||||
use smallvec::SmallVec;
|
||||
use std::{iter, mem, num::NonZeroU32, ptr};
|
||||
use thiserror::Error;
|
||||
|
||||
@ -212,8 +211,10 @@ pub enum QueueSubmitError {
|
||||
DestroyedTexture(id::TextureId),
|
||||
#[error(transparent)]
|
||||
Unmap(#[from] BufferAccessError),
|
||||
#[error("swap chain output was dropped before the command buffer got submitted")]
|
||||
SwapChainOutputDropped,
|
||||
#[error("surface output was dropped before the command buffer got submitted")]
|
||||
SurfaceOutputDropped,
|
||||
#[error("surface was unconfigured before the command buffer got submitted")]
|
||||
SurfaceUnconfigured,
|
||||
#[error("GPU got stuck :(")]
|
||||
StuckGpu,
|
||||
}
|
||||
@ -510,6 +511,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
let mut token = Token::root();
|
||||
|
||||
let callbacks = {
|
||||
let (mut surface_guard, mut token) = self.surfaces.write(&mut token);
|
||||
let (mut device_guard, mut token) = hub.devices.write(&mut token);
|
||||
let device = device_guard
|
||||
.get_mut(queue_id)
|
||||
@ -520,8 +522,6 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
let mut active_executions = Vec::new();
|
||||
|
||||
{
|
||||
let mut signal_swapchain_semaphores = SmallVec::<[_; 1]>::new();
|
||||
let (mut swap_chain_guard, mut token) = hub.swap_chains.write(&mut token);
|
||||
let (mut command_buffer_guard, mut token) = hub.command_buffers.write(&mut token);
|
||||
|
||||
if !command_buffer_ids.is_empty() {
|
||||
@ -569,16 +569,17 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
// optimize the tracked states
|
||||
cmdbuf.trackers.optimize();
|
||||
|
||||
for sc_id in cmdbuf.used_swap_chains.drain(..) {
|
||||
let sc = &mut swap_chain_guard[sc_id.value];
|
||||
if sc.acquired_texture.is_none() {
|
||||
return Err(QueueSubmitError::SwapChainOutputDropped);
|
||||
for surface_id in cmdbuf.used_surfaces.drain(..) {
|
||||
let surface = &mut surface_guard[surface_id];
|
||||
let suf = A::get_surface_mut(surface);
|
||||
if suf.acquired_texture.is_none() {
|
||||
return Err(QueueSubmitError::SurfaceOutputDropped);
|
||||
}
|
||||
if sc.active_submission_index != submit_index {
|
||||
sc.active_submission_index = submit_index;
|
||||
// Only add a signal if this is the first time for this swapchain
|
||||
// to be used in the submission.
|
||||
signal_swapchain_semaphores.push(sc_id.value);
|
||||
match surface.presentation {
|
||||
Some(ref mut present) => {
|
||||
present.active_submission_index = submit_index;
|
||||
}
|
||||
None => return Err(QueueSubmitError::SurfaceUnconfigured),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ pub enum Action<'a> {
|
||||
desc: crate::device::DeviceDescriptor<'a>,
|
||||
backend: wgt::Backend,
|
||||
},
|
||||
ConfigureSurface(id::SurfaceId, wgt::SurfaceConfiguration),
|
||||
CreateBuffer(id::BufferId, crate::resource::BufferDescriptor<'a>),
|
||||
FreeBuffer(id::BufferId),
|
||||
DestroyBuffer(id::BufferId),
|
||||
@ -53,12 +54,11 @@ pub enum Action<'a> {
|
||||
DestroyTextureView(id::TextureViewId),
|
||||
CreateSampler(id::SamplerId, crate::resource::SamplerDescriptor<'a>),
|
||||
DestroySampler(id::SamplerId),
|
||||
CreateSwapChain(id::SwapChainId, wgt::SwapChainDescriptor),
|
||||
GetSwapChainTexture {
|
||||
GetSurfaceTexture {
|
||||
id: id::TextureViewId,
|
||||
parent_id: id::SwapChainId,
|
||||
parent_id: id::SurfaceId,
|
||||
},
|
||||
PresentSwapChain(id::SwapChainId),
|
||||
Present(id::SurfaceId),
|
||||
CreateBindGroupLayout(
|
||||
id::BindGroupLayoutId,
|
||||
crate::binding_model::BindGroupLayoutDescriptor<'a>,
|
||||
|
@ -3,10 +3,9 @@ use crate::{
|
||||
command::{CommandBuffer, RenderBundle},
|
||||
device::Device,
|
||||
id,
|
||||
instance::{Adapter, Instance, Surface},
|
||||
instance::{Adapter, HalSurface, Instance, Surface},
|
||||
pipeline::{ComputePipeline, RenderPipeline, ShaderModule},
|
||||
resource::{Buffer, QuerySet, Sampler, Texture, TextureView},
|
||||
swap_chain::SwapChain,
|
||||
Epoch, Index,
|
||||
};
|
||||
|
||||
@ -111,7 +110,7 @@ impl<T, I: id::TypedId> ops::IndexMut<id::Valid<I>> for Storage<T, I> {
|
||||
}
|
||||
|
||||
impl<T, I: id::TypedId> Storage<T, I> {
|
||||
pub(crate) fn contains(&self, id: I) -> bool {
|
||||
pub(crate) fn _contains(&self, id: I) -> bool {
|
||||
let (index, epoch, _) = id.unzip();
|
||||
match self.map[index as usize] {
|
||||
Element::Vacant => false,
|
||||
@ -201,7 +200,7 @@ impl<T, I: id::TypedId> Storage<T, I> {
|
||||
}
|
||||
|
||||
// Prevents panic on out of range access, allows Vacant elements.
|
||||
pub(crate) fn try_remove(&mut self, id: I) -> Option<T> {
|
||||
pub(crate) fn _try_remove(&mut self, id: I) -> Option<T> {
|
||||
let (index, epoch, _) = id.unzip();
|
||||
if index as usize >= self.map.len() {
|
||||
None
|
||||
@ -264,8 +263,6 @@ impl<A: hal::Api> Access<Adapter<A>> for Surface {}
|
||||
impl<A: hal::Api> Access<Device<A>> for Root {}
|
||||
impl<A: hal::Api> Access<Device<A>> for Surface {}
|
||||
impl<A: hal::Api> Access<Device<A>> for Adapter<A> {}
|
||||
impl<A: hal::Api> Access<SwapChain<A>> for Root {}
|
||||
impl<A: hal::Api> Access<SwapChain<A>> for Device<A> {}
|
||||
impl<A: hal::Api> Access<PipelineLayout<A>> for Root {}
|
||||
impl<A: hal::Api> Access<PipelineLayout<A>> for Device<A> {}
|
||||
impl<A: hal::Api> Access<PipelineLayout<A>> for RenderBundle {}
|
||||
@ -279,7 +276,6 @@ impl<A: hal::Api> Access<BindGroup<A>> for PipelineLayout<A> {}
|
||||
impl<A: hal::Api> Access<BindGroup<A>> for CommandBuffer<A> {}
|
||||
impl<A: hal::Api> Access<CommandBuffer<A>> for Root {}
|
||||
impl<A: hal::Api> Access<CommandBuffer<A>> for Device<A> {}
|
||||
impl<A: hal::Api> Access<CommandBuffer<A>> for SwapChain<A> {} //TODO: remove this (only used in `submit()`)
|
||||
impl<A: hal::Api> Access<RenderBundle> for Device<A> {}
|
||||
impl<A: hal::Api> Access<RenderBundle> for CommandBuffer<A> {}
|
||||
impl<A: hal::Api> Access<ComputePipeline<A>> for Device<A> {}
|
||||
@ -307,7 +303,6 @@ impl<A: hal::Api> Access<Texture<A>> for Root {}
|
||||
impl<A: hal::Api> Access<Texture<A>> for Device<A> {}
|
||||
impl<A: hal::Api> Access<Texture<A>> for Buffer<A> {}
|
||||
impl<A: hal::Api> Access<TextureView<A>> for Root {}
|
||||
impl<A: hal::Api> Access<TextureView<A>> for SwapChain<A> {} //TODO: remove this (only used in `get_next_texture()`)
|
||||
impl<A: hal::Api> Access<TextureView<A>> for Device<A> {}
|
||||
impl<A: hal::Api> Access<TextureView<A>> for Texture<A> {}
|
||||
impl<A: hal::Api> Access<Sampler<A>> for Root {}
|
||||
@ -395,7 +390,6 @@ impl<I: id::TypedId + Debug> IdentityHandlerFactory<I> for IdentityManagerFactor
|
||||
pub trait GlobalIdentityHandlerFactory:
|
||||
IdentityHandlerFactory<id::AdapterId>
|
||||
+ IdentityHandlerFactory<id::DeviceId>
|
||||
+ IdentityHandlerFactory<id::SwapChainId>
|
||||
+ IdentityHandlerFactory<id::PipelineLayoutId>
|
||||
+ IdentityHandlerFactory<id::ShaderModuleId>
|
||||
+ IdentityHandlerFactory<id::BindGroupLayoutId>
|
||||
@ -559,7 +553,6 @@ impl<T: Resource, I: id::TypedId + Copy, F: IdentityHandlerFactory<I>> Registry<
|
||||
pub struct HubReport {
|
||||
pub adapters: StorageReport,
|
||||
pub devices: StorageReport,
|
||||
pub swap_chains: StorageReport,
|
||||
pub pipeline_layouts: StorageReport,
|
||||
pub shader_modules: StorageReport,
|
||||
pub bind_group_layouts: StorageReport,
|
||||
@ -584,7 +577,6 @@ impl HubReport {
|
||||
pub struct Hub<A: hal::Api, F: GlobalIdentityHandlerFactory> {
|
||||
pub adapters: Registry<Adapter<A>, id::AdapterId, F>,
|
||||
pub devices: Registry<Device<A>, id::DeviceId, F>,
|
||||
pub swap_chains: Registry<SwapChain<A>, id::SwapChainId, F>,
|
||||
pub pipeline_layouts: Registry<PipelineLayout<A>, id::PipelineLayoutId, F>,
|
||||
pub shader_modules: Registry<ShaderModule<A>, id::ShaderModuleId, F>,
|
||||
pub bind_group_layouts: Registry<BindGroupLayout<A>, id::BindGroupLayoutId, F>,
|
||||
@ -605,7 +597,6 @@ impl<A: HalApi, F: GlobalIdentityHandlerFactory> Hub<A, F> {
|
||||
Self {
|
||||
adapters: Registry::new(A::VARIANT, factory),
|
||||
devices: Registry::new(A::VARIANT, factory),
|
||||
swap_chains: Registry::new(A::VARIANT, factory),
|
||||
pipeline_layouts: Registry::new(A::VARIANT, factory),
|
||||
shader_modules: Registry::new(A::VARIANT, factory),
|
||||
bind_group_layouts: Registry::new(A::VARIANT, factory),
|
||||
@ -664,7 +655,7 @@ impl<A: HalApi, F: GlobalIdentityHandlerFactory> Hub<A, F> {
|
||||
device.raw.destroy_texture_view(texture_view.raw);
|
||||
}
|
||||
}
|
||||
TextureViewSource::SwapChain(_) => {} //TODO
|
||||
TextureViewSource::Surface(_) => {} //TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -731,16 +722,13 @@ impl<A: HalApi, F: GlobalIdentityHandlerFactory> Hub<A, F> {
|
||||
}
|
||||
}
|
||||
|
||||
for (index, element) in self.swap_chains.data.write().map.drain(..).enumerate() {
|
||||
if let Element::Occupied(swap_chain, epoch) = element {
|
||||
let device = &devices[swap_chain.device_id.value];
|
||||
let suf_id = id::TypedId::zip(index as Index, epoch, A::VARIANT);
|
||||
//TODO: hold the surface alive by the swapchain
|
||||
if surface_guard.contains(suf_id) {
|
||||
let surface = surface_guard.get_mut(suf_id).unwrap();
|
||||
let suf = A::get_surface_mut(surface);
|
||||
for element in surface_guard.map.drain(..) {
|
||||
if let Element::Occupied(mut surface, _epoch) = element {
|
||||
if let Some(present) = surface.presentation.take() {
|
||||
let device = &devices[present.device_id.value];
|
||||
let suf = A::get_surface_mut(&mut surface);
|
||||
unsafe {
|
||||
suf.unconfigure(&device.raw);
|
||||
suf.raw.unconfigure(&device.raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -771,7 +759,6 @@ impl<A: HalApi, F: GlobalIdentityHandlerFactory> Hub<A, F> {
|
||||
HubReport {
|
||||
adapters: self.adapters.data.read().generate_report(),
|
||||
devices: self.devices.data.read().generate_report(),
|
||||
swap_chains: self.swap_chains.data.read().generate_report(),
|
||||
pipeline_layouts: self.pipeline_layouts.data.read().generate_report(),
|
||||
shader_modules: self.shader_modules.data.read().generate_report(),
|
||||
bind_group_layouts: self.bind_group_layouts.data.read().generate_report(),
|
||||
@ -951,7 +938,8 @@ pub trait HalApi: hal::Api {
|
||||
const VARIANT: Backend;
|
||||
fn create_instance_from_hal(name: &str, hal_instance: Self::Instance) -> Instance;
|
||||
fn hub<G: GlobalIdentityHandlerFactory>(global: &Global<G>) -> &Hub<Self, G>;
|
||||
fn get_surface_mut(surface: &mut Surface) -> &mut Self::Surface;
|
||||
fn get_surface(surface: &Surface) -> &HalSurface<Self>;
|
||||
fn get_surface_mut(surface: &mut Surface) -> &mut HalSurface<Self>;
|
||||
}
|
||||
|
||||
#[cfg(vulkan)]
|
||||
@ -967,7 +955,10 @@ impl HalApi for hal::api::Vulkan {
|
||||
fn hub<G: GlobalIdentityHandlerFactory>(global: &Global<G>) -> &Hub<Self, G> {
|
||||
&global.hubs.vulkan
|
||||
}
|
||||
fn get_surface_mut(surface: &mut Surface) -> &mut Self::Surface {
|
||||
fn get_surface(surface: &Surface) -> &HalSurface<Self> {
|
||||
surface.vulkan.as_ref().unwrap()
|
||||
}
|
||||
fn get_surface_mut(surface: &mut Surface) -> &mut HalSurface<Self> {
|
||||
surface.vulkan.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
@ -984,7 +975,10 @@ impl HalApi for hal::api::Metal {
|
||||
fn hub<G: GlobalIdentityHandlerFactory>(global: &Global<G>) -> &Hub<Self, G> {
|
||||
&global.hubs.metal
|
||||
}
|
||||
fn get_surface_mut(surface: &mut Surface) -> &mut Self::Surface {
|
||||
fn get_surface(surface: &Surface) -> &HalSurface<Self> {
|
||||
surface.metal.as_ref().unwrap()
|
||||
}
|
||||
fn get_surface_mut(surface: &mut Surface) -> &mut HalSurface<Self> {
|
||||
surface.metal.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
@ -1002,7 +996,10 @@ impl HalApi for hal::api::Dx12 {
|
||||
fn hub<G: GlobalIdentityHandlerFactory>(global: &Global<G>) -> &Hub<Self, G> {
|
||||
&global.hubs.dx12
|
||||
}
|
||||
fn get_surface_mut(surface: &mut Surface) -> &mut Self::Surface {
|
||||
fn get_surface(surface: &Surface) -> &HalSurface<Self> {
|
||||
surface.dx12.as_ref().unwrap()
|
||||
}
|
||||
fn get_surface_mut(surface: &mut Surface) -> &mut HalSurface<Self> {
|
||||
surface.dx12.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
@ -1014,7 +1011,10 @@ impl HalApi for hal::api::Dx11 {
|
||||
fn hub<G: GlobalIdentityHandlerFactory>(global: &Global<G>) -> &Hub<Self, G> {
|
||||
&global.hubs.dx11
|
||||
}
|
||||
fn get_surface_mut(surface: &mut Surface) -> &mut Self::Surface {
|
||||
fn get_surface(surface: &Surface) -> &HalSurface<Self> {
|
||||
surface.dx11.as_ref().unwrap()
|
||||
}
|
||||
fn get_surface_mut(surface: &mut Surface) -> &mut HalSurface<Self> {
|
||||
surface.dx11.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
@ -1033,7 +1033,10 @@ impl HalApi for hal::api::Gles {
|
||||
fn hub<G: GlobalIdentityHandlerFactory>(global: &Global<G>) -> &Hub<Self, G> {
|
||||
&global.hubs.gl
|
||||
}
|
||||
fn get_surface_mut(surface: &mut Surface) -> &mut Self::Surface {
|
||||
fn get_surface(surface: &Surface) -> &HalSurface<Self> {
|
||||
surface.gl.as_ref().unwrap()
|
||||
}
|
||||
fn get_surface_mut(surface: &mut Surface) -> &mut HalSurface<Self> {
|
||||
surface.gl.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
@ -161,21 +161,6 @@ pub type ComputePassEncoderId = *mut crate::command::ComputePass;
|
||||
pub type RenderBundleEncoderId = *mut crate::command::RenderBundleEncoder;
|
||||
pub type RenderBundleId = Id<crate::command::RenderBundle>;
|
||||
pub type QuerySetId = Id<crate::resource::QuerySet<Dummy>>;
|
||||
// Swap chain
|
||||
pub type SwapChainId = Id<crate::swap_chain::SwapChain<Dummy>>;
|
||||
|
||||
impl SurfaceId {
|
||||
pub(crate) fn to_swap_chain_id(self, backend: Backend) -> SwapChainId {
|
||||
let (index, epoch, _) = self.unzip();
|
||||
Id::zip(index, epoch, backend)
|
||||
}
|
||||
}
|
||||
impl SwapChainId {
|
||||
pub fn to_surface_id(self) -> SurfaceId {
|
||||
let (index, epoch, _) = self.unzip();
|
||||
Id::zip(index, epoch, Backend::Empty)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_id_backend() {
|
||||
|
@ -2,6 +2,7 @@ use crate::{
|
||||
device::{Device, DeviceDescriptor},
|
||||
hub::{Global, GlobalIdentityHandlerFactory, HalApi, Input, Token},
|
||||
id::{AdapterId, DeviceId, SurfaceId, Valid},
|
||||
present::Presentation,
|
||||
LabelHelpers, LifeGuard, Stored, DOWNLEVEL_WARNING_MESSAGE,
|
||||
};
|
||||
|
||||
@ -12,7 +13,10 @@ use thiserror::Error;
|
||||
|
||||
pub type RequestAdapterOptions = wgt::RequestAdapterOptions<SurfaceId>;
|
||||
type HalInstance<A> = <A as hal::Api>::Instance;
|
||||
type HalSurface<A> = <A as hal::Api>::Surface;
|
||||
pub struct HalSurface<A: hal::Api> {
|
||||
pub raw: A::Surface,
|
||||
pub acquired_texture: Option<A::SurfaceTexture>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[error("Limit '{name}' value {requested} is better than allowed {allowed}")]
|
||||
@ -124,7 +128,7 @@ impl Instance {
|
||||
let map = |(surface_backend, self_backend)| {
|
||||
unsafe {
|
||||
if let Some(suf) = surface_backend {
|
||||
self_backend.as_ref().unwrap().destroy_surface(suf);
|
||||
self_backend.as_ref().unwrap().destroy_surface(suf.raw);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -144,6 +148,7 @@ impl Instance {
|
||||
}
|
||||
|
||||
pub struct Surface {
|
||||
pub(crate) presentation: Option<Presentation>,
|
||||
#[cfg(vulkan)]
|
||||
pub vulkan: Option<HalSurface<hal::api::Vulkan>>,
|
||||
#[cfg(metal)]
|
||||
@ -168,6 +173,38 @@ impl crate::hub::Resource for Surface {
|
||||
}
|
||||
}
|
||||
|
||||
impl Surface {
|
||||
pub fn get_preferred_format<A: HalApi>(
|
||||
&self,
|
||||
adapter: &Adapter<A>,
|
||||
) -> Result<wgt::TextureFormat, GetSurfacePreferredFormatError> {
|
||||
// Check the four formats mentioned in the WebGPU spec.
|
||||
// Also, prefer sRGB over linear as it is better in
|
||||
// representing perceived colors.
|
||||
let preferred_formats = [
|
||||
wgt::TextureFormat::Bgra8UnormSrgb,
|
||||
wgt::TextureFormat::Rgba8UnormSrgb,
|
||||
wgt::TextureFormat::Bgra8Unorm,
|
||||
wgt::TextureFormat::Rgba8Unorm,
|
||||
];
|
||||
|
||||
let suf = A::get_surface(self);
|
||||
let caps = unsafe {
|
||||
adapter
|
||||
.raw
|
||||
.adapter
|
||||
.surface_capabilities(&suf.raw)
|
||||
.ok_or(GetSurfacePreferredFormatError::UnsupportedQueueFamily)?
|
||||
};
|
||||
|
||||
preferred_formats
|
||||
.iter()
|
||||
.cloned()
|
||||
.find(|preferred| caps.formats.contains(preferred))
|
||||
.ok_or(GetSurfacePreferredFormatError::NotFound)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Adapter<A: hal::Api> {
|
||||
pub(crate) raw: hal::ExposedAdapter<A>,
|
||||
life_guard: LifeGuard,
|
||||
@ -181,41 +218,9 @@ impl<A: HalApi> Adapter<A> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_surface_supported(&self, surface: &mut Surface) -> bool {
|
||||
unsafe {
|
||||
self.raw
|
||||
.adapter
|
||||
.surface_capabilities(A::get_surface_mut(surface))
|
||||
}
|
||||
.is_some()
|
||||
}
|
||||
|
||||
pub fn get_swap_chain_preferred_format(
|
||||
&self,
|
||||
surface: &mut Surface,
|
||||
) -> Result<wgt::TextureFormat, GetSwapChainPreferredFormatError> {
|
||||
// Check the four formats mentioned in the WebGPU spec.
|
||||
// Also, prefer sRGB over linear as it is better in
|
||||
// representing perceived colors.
|
||||
let preferred_formats = [
|
||||
wgt::TextureFormat::Bgra8UnormSrgb,
|
||||
wgt::TextureFormat::Rgba8UnormSrgb,
|
||||
wgt::TextureFormat::Bgra8Unorm,
|
||||
wgt::TextureFormat::Rgba8Unorm,
|
||||
];
|
||||
|
||||
let caps = unsafe {
|
||||
self.raw
|
||||
.adapter
|
||||
.surface_capabilities(A::get_surface_mut(surface))
|
||||
.ok_or(GetSwapChainPreferredFormatError::UnsupportedQueueFamily)?
|
||||
};
|
||||
|
||||
preferred_formats
|
||||
.iter()
|
||||
.cloned()
|
||||
.find(|preferred| caps.formats.contains(preferred))
|
||||
.ok_or(GetSwapChainPreferredFormatError::NotFound)
|
||||
pub fn is_surface_supported(&self, surface: &Surface) -> bool {
|
||||
let suf = A::get_surface(surface);
|
||||
unsafe { self.raw.adapter.surface_capabilities(&suf.raw) }.is_some()
|
||||
}
|
||||
|
||||
pub(crate) fn get_texture_format_features(
|
||||
@ -362,7 +367,7 @@ pub enum IsSurfaceSupportedError {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
pub enum GetSwapChainPreferredFormatError {
|
||||
pub enum GetSurfacePreferredFormatError {
|
||||
#[error("no suitable format found")]
|
||||
NotFound,
|
||||
#[error("invalid adapter")]
|
||||
@ -433,29 +438,39 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
) -> SurfaceId {
|
||||
profiling::scope!("create_surface", "Instance");
|
||||
|
||||
let surface = unsafe {
|
||||
backends_map! {
|
||||
let map = |inst| {
|
||||
inst
|
||||
.as_ref()
|
||||
.and_then(|inst| inst.create_surface(handle).map_err(|e| {
|
||||
//Note: using adummy argument to work around the following error:
|
||||
//> cannot provide explicit generic arguments when `impl Trait` is used in argument position
|
||||
fn init<A: hal::Api>(
|
||||
_: A,
|
||||
inst: &Option<A::Instance>,
|
||||
handle: &impl raw_window_handle::HasRawWindowHandle,
|
||||
) -> Option<HalSurface<A>> {
|
||||
inst.as_ref().and_then(|inst| unsafe {
|
||||
match inst.create_surface(handle) {
|
||||
Ok(raw) => Some(HalSurface {
|
||||
raw,
|
||||
acquired_texture: None,
|
||||
}),
|
||||
Err(e) => {
|
||||
log::warn!("Error: {:?}", e);
|
||||
}).ok())
|
||||
};
|
||||
|
||||
Surface {
|
||||
#[cfg(vulkan)]
|
||||
vulkan: map(&self.instance.vulkan),
|
||||
#[cfg(metal)]
|
||||
metal: map(&self.instance.metal),
|
||||
#[cfg(dx12)]
|
||||
dx12: map(&self.instance.dx12),
|
||||
#[cfg(dx11)]
|
||||
dx11: map(&self.instance.dx11),
|
||||
#[cfg(gl)]
|
||||
gl: map(&self.instance.gl),
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let surface = Surface {
|
||||
presentation: None,
|
||||
#[cfg(vulkan)]
|
||||
vulkan: init(hal::api::Vulkan, &self.instance.vulkan, handle),
|
||||
#[cfg(metal)]
|
||||
metal: init(hal::api::Metal, &self.instance.metal, handle),
|
||||
#[cfg(dx12)]
|
||||
dx12: init(hal::api::Dx12, &self.instance.dx12, handle),
|
||||
#[cfg(dx11)]
|
||||
dx11: init(hal::api::Dx11, &self.instance.dx11, handle),
|
||||
#[cfg(gl)]
|
||||
gl: init(hal::api::Gles, &self.instance.gl, handle),
|
||||
};
|
||||
|
||||
let mut token = Token::root();
|
||||
@ -472,10 +487,14 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
profiling::scope!("create_surface_metal", "Instance");
|
||||
|
||||
let surface = Surface {
|
||||
metal: self.instance.metal.as_ref().map(|inst| {
|
||||
// we don't want to link to metal-rs for this
|
||||
#[allow(clippy::transmute_ptr_to_ref)]
|
||||
inst.create_surface_from_layer(unsafe { std::mem::transmute(layer) })
|
||||
presentation: None,
|
||||
metal: self.instance.metal.as_ref().map(|inst| HalSurface {
|
||||
raw: {
|
||||
// we don't want to link to metal-rs for this
|
||||
#[allow(clippy::transmute_ptr_to_ref)]
|
||||
inst.create_surface_from_layer(unsafe { std::mem::transmute(layer) })
|
||||
},
|
||||
acquired_texture: None,
|
||||
}),
|
||||
};
|
||||
|
||||
@ -563,7 +582,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
let mut adapters = unsafe { inst.enumerate_adapters() };
|
||||
if let Some(surface_backend) = compatible_surface.and_then(surface_backend) {
|
||||
adapters.retain(|exposed| unsafe {
|
||||
exposed.adapter.surface_capabilities(surface_backend).is_some()
|
||||
exposed.adapter.surface_capabilities(&surface_backend.raw).is_some()
|
||||
});
|
||||
}
|
||||
device_types.extend(adapters.iter().map(|ad| ad.info.device_type));
|
||||
|
@ -40,8 +40,8 @@ pub mod id;
|
||||
pub mod instance;
|
||||
mod memory_init_tracker;
|
||||
pub mod pipeline;
|
||||
pub mod present;
|
||||
pub mod resource;
|
||||
pub mod swap_chain;
|
||||
mod track;
|
||||
mod validation;
|
||||
|
||||
|
@ -30,26 +30,6 @@ macro_rules! backends_map {
|
||||
}
|
||||
)*
|
||||
};
|
||||
|
||||
// a struct constructor with one field per backend with mapped data
|
||||
(
|
||||
let map = |$backend:pat| $map:block;
|
||||
$Struct:ident {
|
||||
$(
|
||||
#[cfg($backend_cfg:meta)] $ident:ident : map($expr:expr),
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
$Struct {
|
||||
$(
|
||||
#[cfg($backend_cfg)]
|
||||
$ident: {
|
||||
let $backend = $expr;
|
||||
$map
|
||||
},
|
||||
)*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -69,13 +49,16 @@ fn test_backend_macro() {
|
||||
}
|
||||
|
||||
// test struct construction
|
||||
let test_foo: Foo = backends_map! {
|
||||
let map = |init| { init - 100 };
|
||||
let test_foo: Foo = {
|
||||
Foo {
|
||||
#[cfg(vulkan)] vulkan: map(101),
|
||||
#[cfg(metal)] metal: map(102),
|
||||
#[cfg(dx12)] dx12: map(103),
|
||||
#[cfg(dx11)] dx11: map(104),
|
||||
#[cfg(vulkan)]
|
||||
vulkan: 101,
|
||||
#[cfg(metal)]
|
||||
metal: 102,
|
||||
#[cfg(dx12)]
|
||||
dx12: 103,
|
||||
#[cfg(dx11)]
|
||||
dx11: 104,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,31 +1,11 @@
|
||||
/*! Swap chain management.
|
||||
/*! Presentation.
|
||||
|
||||
## Lifecycle
|
||||
|
||||
At the low level, the swap chain is using the new simplified model of gfx-rs.
|
||||
|
||||
A swap chain is a separate object that is backend-dependent but shares the index with
|
||||
the parent surface, which is backend-independent. This ensures a 1:1 correspondence
|
||||
between them.
|
||||
|
||||
`get_next_image()` requests a new image from the surface. It becomes a part of
|
||||
`TextureViewInner::SwapChain` of the resulted view. The view is registered in the HUB
|
||||
but not in the device tracker.
|
||||
|
||||
The only operation allowed on the view is to be either a color or a resolve attachment.
|
||||
It can only be used in one command buffer, which needs to be submitted before presenting.
|
||||
Command buffer tracker knows about the view, but only for the duration of recording.
|
||||
The view ID is erased from it at the end, so that it's not merged into the device tracker.
|
||||
|
||||
When a swapchain view is used in `begin_render_pass()`, we assume the start and end image
|
||||
layouts purely based on whether or not this view was used in this command buffer before.
|
||||
It always starts with `Uninitialized` and ends with `Present`, so that no barriers are
|
||||
needed when we need to actually present it.
|
||||
|
||||
In `queue_submit()` we make sure to signal the semaphore whenever we render to a swap
|
||||
chain view.
|
||||
|
||||
In `present()` we return the swap chain image back and wait on the semaphore.
|
||||
!*/
|
||||
|
||||
#[cfg(feature = "trace")]
|
||||
@ -33,62 +13,52 @@ use crate::device::trace::Action;
|
||||
use crate::{
|
||||
device::DeviceError,
|
||||
hub::{Global, GlobalIdentityHandlerFactory, HalApi, Input, Token},
|
||||
id::{DeviceId, SwapChainId, TextureViewId, Valid},
|
||||
id::{DeviceId, SurfaceId, TextureViewId, Valid},
|
||||
resource,
|
||||
track::TextureSelector,
|
||||
LifeGuard, Stored, SubmissionIndex,
|
||||
};
|
||||
|
||||
use hal::{Device as _, Queue as _, Surface as _};
|
||||
use std::{borrow::Borrow, marker::PhantomData};
|
||||
use std::borrow::Borrow;
|
||||
use thiserror::Error;
|
||||
use wgt::SwapChainStatus as Status;
|
||||
use wgt::SurfaceStatus as Status;
|
||||
|
||||
const FRAME_TIMEOUT_MS: u32 = 1000;
|
||||
pub const DESIRED_NUM_FRAMES: u32 = 3;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SwapChain<A: hal::Api> {
|
||||
pub(crate) life_guard: LifeGuard,
|
||||
pub(crate) struct Presentation {
|
||||
pub(crate) device_id: Stored<DeviceId>,
|
||||
pub(crate) desc: wgt::SwapChainDescriptor,
|
||||
pub(crate) config: wgt::SurfaceConfiguration,
|
||||
pub(crate) num_frames: u32,
|
||||
pub(crate) acquired_texture: Option<(Stored<TextureViewId>, A::SurfaceTexture)>,
|
||||
pub(crate) acquired_texture: Option<Stored<TextureViewId>>,
|
||||
pub(crate) active_submission_index: SubmissionIndex,
|
||||
pub(crate) marker: PhantomData<A>,
|
||||
}
|
||||
|
||||
impl<A: hal::Api> crate::hub::Resource for SwapChain<A> {
|
||||
const TYPE: &'static str = "SwapChain";
|
||||
|
||||
fn life_guard(&self) -> &LifeGuard {
|
||||
&self.life_guard
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
pub enum SwapChainError {
|
||||
#[error("swap chain is invalid")]
|
||||
pub enum SurfaceError {
|
||||
#[error("surface is invalid")]
|
||||
Invalid,
|
||||
#[error("parent surface is invalid")]
|
||||
InvalidSurface,
|
||||
#[error("surface is not configured for presentation")]
|
||||
NotConfigured,
|
||||
#[error(transparent)]
|
||||
Device(#[from] DeviceError),
|
||||
#[error("swap chain image is already acquired")]
|
||||
#[error("surface image is already acquired")]
|
||||
AlreadyAcquired,
|
||||
#[error("acquired frame is still referenced")]
|
||||
StillReferenced,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
pub enum CreateSwapChainError {
|
||||
pub enum ConfigureSurfaceError {
|
||||
#[error(transparent)]
|
||||
Device(#[from] DeviceError),
|
||||
#[error("invalid surface")]
|
||||
InvalidSurface,
|
||||
#[error("`SwapChainOutput` must be dropped before a new `SwapChain` is made")]
|
||||
SwapChainOutputExists,
|
||||
#[error("Both `SwapChain` width and height must be non-zero. Wait to recreate the `SwapChain` until the window has non-zero area.")]
|
||||
#[error("`SurfaceOutput` must be dropped before a new `Surface` is made")]
|
||||
PreviousOutputExists,
|
||||
#[error("Both `Surface` width and height must be non-zero. Wait to recreate the `Surface` until the window has non-zero area.")]
|
||||
ZeroArea,
|
||||
#[error("surface does not support the adapter's queue family")]
|
||||
UnsupportedQueueFamily,
|
||||
@ -103,17 +73,17 @@ pub enum CreateSwapChainError {
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct SwapChainOutput {
|
||||
pub struct SurfaceOutput {
|
||||
pub status: Status,
|
||||
pub view_id: Option<TextureViewId>,
|
||||
}
|
||||
|
||||
impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
pub fn swap_chain_get_current_texture_view<A: HalApi>(
|
||||
pub fn surface_get_current_texture_view<A: HalApi>(
|
||||
&self,
|
||||
swap_chain_id: SwapChainId,
|
||||
surface_id: SurfaceId,
|
||||
view_id_in: Input<G, TextureViewId>,
|
||||
) -> Result<SwapChainOutput, SwapChainError> {
|
||||
) -> Result<SurfaceOutput, SurfaceError> {
|
||||
profiling::scope!("get_next_texture", "SwapChain");
|
||||
|
||||
let hub = A::hub(self);
|
||||
@ -122,25 +92,26 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
|
||||
let (mut surface_guard, mut token) = self.surfaces.write(&mut token);
|
||||
let surface = surface_guard
|
||||
.get_mut(swap_chain_id.to_surface_id())
|
||||
.map_err(|_| SwapChainError::InvalidSurface)?;
|
||||
.get_mut(surface_id)
|
||||
.map_err(|_| SurfaceError::Invalid)?;
|
||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||
let (mut swap_chain_guard, mut token) = hub.swap_chains.write(&mut token);
|
||||
let sc = swap_chain_guard
|
||||
.get_mut(swap_chain_id)
|
||||
.map_err(|_| SwapChainError::Invalid)?;
|
||||
|
||||
let device = &device_guard[sc.device_id.value];
|
||||
let device = match surface.presentation {
|
||||
Some(ref present) => &device_guard[present.device_id.value],
|
||||
None => return Err(SurfaceError::NotConfigured),
|
||||
};
|
||||
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(ref trace) = device.trace {
|
||||
trace.lock().add(Action::GetSwapChainTexture {
|
||||
trace.lock().add(Action::GetSurfaceTexture {
|
||||
id: fid.id(),
|
||||
parent_id: swap_chain_id,
|
||||
parent_id: surface_id,
|
||||
});
|
||||
}
|
||||
|
||||
let config = surface.presentation.as_ref().unwrap().config.clone();
|
||||
let suf = A::get_surface_mut(surface);
|
||||
let (texture, status) = match unsafe { suf.acquire_texture(FRAME_TIMEOUT_MS) } {
|
||||
let (texture, status) = match unsafe { suf.raw.acquire_texture(FRAME_TIMEOUT_MS) } {
|
||||
Ok(Some(ast)) => {
|
||||
let status = if ast.suboptimal {
|
||||
Status::Suboptimal
|
||||
@ -168,7 +139,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
|
||||
let hal_desc = hal::TextureViewDescriptor {
|
||||
label: Some("_Frame"),
|
||||
format: sc.desc.format,
|
||||
format: config.format,
|
||||
dimension: wgt::TextureViewDimension::D2,
|
||||
usage: hal::TextureUses::COLOR_TARGET,
|
||||
range: wgt::ImageSubresourceRange::default(),
|
||||
@ -184,12 +155,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
};
|
||||
let view = resource::TextureView {
|
||||
raw,
|
||||
source: resource::TextureViewSource::SwapChain(Stored {
|
||||
value: Valid(swap_chain_id),
|
||||
ref_count: sc.life_guard.add_ref(),
|
||||
}),
|
||||
source: resource::TextureViewSource::Surface(Valid(surface_id)),
|
||||
desc: resource::HalTextureViewDescriptor {
|
||||
format: sc.desc.format,
|
||||
format: config.format,
|
||||
dimension: wgt::TextureViewDimension::D2,
|
||||
range: wgt::ImageSubresourceRange::default(),
|
||||
},
|
||||
@ -199,8 +167,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
filterable: false,
|
||||
},
|
||||
extent: wgt::Extent3d {
|
||||
width: sc.desc.width,
|
||||
height: sc.desc.height,
|
||||
width: config.width,
|
||||
height: config.height,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
samples: 1,
|
||||
@ -215,30 +183,29 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
let ref_count = view.life_guard.add_ref();
|
||||
let id = fid.assign(view, &mut token);
|
||||
|
||||
if sc.acquired_texture.is_some() {
|
||||
return Err(SwapChainError::AlreadyAcquired);
|
||||
}
|
||||
suf.acquired_texture = Some(suf_texture);
|
||||
|
||||
sc.acquired_texture = Some((
|
||||
Stored {
|
||||
value: id,
|
||||
ref_count,
|
||||
},
|
||||
suf_texture,
|
||||
));
|
||||
let present = surface.presentation.as_mut().unwrap();
|
||||
if present.acquired_texture.is_some() {
|
||||
return Err(SurfaceError::AlreadyAcquired);
|
||||
}
|
||||
present.acquired_texture = Some(Stored {
|
||||
value: id,
|
||||
ref_count,
|
||||
});
|
||||
|
||||
Some(id.0)
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
Ok(SwapChainOutput { status, view_id })
|
||||
Ok(SurfaceOutput { status, view_id })
|
||||
}
|
||||
|
||||
pub fn swap_chain_present<A: HalApi>(
|
||||
pub fn surface_present<A: HalApi>(
|
||||
&self,
|
||||
swap_chain_id: SwapChainId,
|
||||
) -> Result<Status, SwapChainError> {
|
||||
surface_id: SurfaceId,
|
||||
) -> Result<Status, SurfaceError> {
|
||||
profiling::scope!("present", "SwapChain");
|
||||
|
||||
let hub = A::hub(self);
|
||||
@ -246,40 +213,40 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
|
||||
let (mut surface_guard, mut token) = self.surfaces.write(&mut token);
|
||||
let surface = surface_guard
|
||||
.get_mut(swap_chain_id.to_surface_id())
|
||||
.map_err(|_| SwapChainError::InvalidSurface)?;
|
||||
.get_mut(surface_id)
|
||||
.map_err(|_| SurfaceError::Invalid)?;
|
||||
let (mut device_guard, mut token) = hub.devices.write(&mut token);
|
||||
let (mut swap_chain_guard, _) = hub.swap_chains.write(&mut token);
|
||||
let sc = swap_chain_guard
|
||||
.get_mut(swap_chain_id)
|
||||
.map_err(|_| SwapChainError::Invalid)?;
|
||||
let device = &mut device_guard[sc.device_id.value];
|
||||
|
||||
let present = match surface.presentation {
|
||||
Some(ref mut present) => present,
|
||||
None => return Err(SurfaceError::NotConfigured),
|
||||
};
|
||||
|
||||
let device = &mut device_guard[present.device_id.value];
|
||||
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(ref trace) = device.trace {
|
||||
trace.lock().add(Action::PresentSwapChain(swap_chain_id));
|
||||
trace.lock().add(Action::Present(surface_id));
|
||||
}
|
||||
|
||||
let suf_texture = {
|
||||
let (view_id, suf_texture) = sc
|
||||
let result = {
|
||||
let view_id = present
|
||||
.acquired_texture
|
||||
.take()
|
||||
.ok_or(SwapChainError::AlreadyAcquired)?;
|
||||
.ok_or(SurfaceError::AlreadyAcquired)?;
|
||||
let suf = A::get_surface_mut(surface);
|
||||
let suf_texture = suf.acquired_texture.take().unwrap();
|
||||
|
||||
drop(swap_chain_guard);
|
||||
let result = unsafe { device.queue.present(&mut suf.raw, suf_texture) };
|
||||
|
||||
drop(surface_guard);
|
||||
|
||||
let (view, _) = hub.texture_views.unregister(view_id.value.0, &mut token);
|
||||
if let Some(view) = view {
|
||||
device.schedule_rogue_texture_view_for_destruction(view_id.value, view, &mut token);
|
||||
}
|
||||
|
||||
suf_texture
|
||||
};
|
||||
|
||||
let result = unsafe {
|
||||
device
|
||||
.queue
|
||||
.present(A::get_surface_mut(surface), suf_texture)
|
||||
result
|
||||
};
|
||||
|
||||
log::debug!("Presented. End of Frame");
|
||||
@ -288,11 +255,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
Ok(()) => Ok(Status::Good),
|
||||
Err(err) => match err {
|
||||
hal::SurfaceError::Lost => Ok(Status::Lost),
|
||||
hal::SurfaceError::Device(err) => Err(SwapChainError::from(DeviceError::from(err))),
|
||||
hal::SurfaceError::Device(err) => Err(SurfaceError::from(DeviceError::from(err))),
|
||||
hal::SurfaceError::Outdated => Ok(Status::Outdated),
|
||||
hal::SurfaceError::Other(msg) => {
|
||||
log::error!("acquire error: {}", msg);
|
||||
Err(SwapChainError::InvalidSurface)
|
||||
Err(SurfaceError::Invalid)
|
||||
}
|
||||
},
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
device::{DeviceError, HostMap, MissingFeatures},
|
||||
hub::Resource,
|
||||
id::{DeviceId, SwapChainId, TextureId},
|
||||
id::{DeviceId, SurfaceId, TextureId, Valid},
|
||||
memory_init_tracker::MemoryInitTracker,
|
||||
track::{TextureSelector, DUMMY_SELECTOR},
|
||||
validation::MissingBufferUsageError,
|
||||
@ -240,7 +240,7 @@ pub struct TextureViewDescriptor<'a> {
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum TextureViewSource {
|
||||
Native(Stored<TextureId>),
|
||||
SwapChain(Stored<SwapChainId>),
|
||||
Surface(Valid<SurfaceId>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -311,8 +311,8 @@ pub enum CreateTextureViewError {
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
pub enum TextureViewDestroyError {
|
||||
#[error("cannot destroy swap chain image")]
|
||||
SwapChainImage,
|
||||
#[error("cannot destroy a surface image")]
|
||||
SurfaceImage,
|
||||
}
|
||||
|
||||
impl<A: hal::Api> Resource for TextureView<A> {
|
||||
|
@ -2366,12 +2366,12 @@ bitflags::bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes a [`SwapChain`].
|
||||
/// Configures a [`Surface`] for presentation.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct SwapChainDescriptor {
|
||||
pub struct SurfaceConfiguration {
|
||||
/// The usage of the swap chain. The only supported usage is `RENDER_ATTACHMENT`.
|
||||
pub usage: TextureUsages,
|
||||
/// The texture format of the swap chain. The only formats that are guaranteed are
|
||||
@ -2386,10 +2386,10 @@ pub struct SwapChainDescriptor {
|
||||
pub present_mode: PresentMode,
|
||||
}
|
||||
|
||||
/// Status of the recieved swapchain image.
|
||||
/// Status of the recieved surface image.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub enum SwapChainStatus {
|
||||
pub enum SurfaceStatus {
|
||||
/// No issues.
|
||||
Good,
|
||||
/// The swap chain is operational, but it does no longer perfectly
|
||||
|
@ -33,7 +33,7 @@ struct Example {
|
||||
impl framework::Example for Example {
|
||||
/// constructs initial instance of Example struct
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
_adapter: &wgpu::Adapter,
|
||||
device: &wgpu::Device,
|
||||
_queue: &wgpu::Queue,
|
||||
@ -143,7 +143,7 @@ impl framework::Example for Example {
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &draw_shader,
|
||||
entry_point: "main",
|
||||
targets: &[sc_desc.format.into()],
|
||||
targets: &[config.format.into()],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState::default(),
|
||||
depth_stencil: None,
|
||||
@ -246,7 +246,7 @@ impl framework::Example for Example {
|
||||
/// resize is called on WindowEvent::Resized events
|
||||
fn resize(
|
||||
&mut self,
|
||||
_sc_desc: &wgpu::SwapChainDescriptor,
|
||||
_sc_desc: &wgpu::SurfaceConfiguration,
|
||||
_device: &wgpu::Device,
|
||||
_queue: &wgpu::Queue,
|
||||
) {
|
||||
|
@ -39,7 +39,7 @@ struct Example {
|
||||
|
||||
impl framework::Example for Example {
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
_adapter: &wgpu::Adapter,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
@ -118,7 +118,7 @@ impl framework::Example for Example {
|
||||
module: &shader,
|
||||
entry_point: "fs_main",
|
||||
targets: &[wgpu::ColorTargetState {
|
||||
format: sc_desc.format,
|
||||
format: config.format,
|
||||
blend: Some(wgpu::BlendState::ALPHA_BLENDING),
|
||||
write_mask: wgpu::ColorWrites::default(),
|
||||
}],
|
||||
@ -179,9 +179,9 @@ impl framework::Example for Example {
|
||||
let globals = Globals {
|
||||
mvp: cgmath::ortho(
|
||||
0.0,
|
||||
sc_desc.width as f32,
|
||||
config.width as f32,
|
||||
0.0,
|
||||
sc_desc.height as f32,
|
||||
config.height as f32,
|
||||
-1.0,
|
||||
1.0,
|
||||
)
|
||||
@ -239,7 +239,7 @@ impl framework::Example for Example {
|
||||
local_group,
|
||||
bunnies: Vec::new(),
|
||||
local_buffer,
|
||||
extent: [sc_desc.width, sc_desc.height],
|
||||
extent: [config.width, config.height],
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,7 +275,7 @@ impl framework::Example for Example {
|
||||
|
||||
fn resize(
|
||||
&mut self,
|
||||
_sc_desc: &wgpu::SwapChainDescriptor,
|
||||
_sc_desc: &wgpu::SurfaceConfiguration,
|
||||
_device: &wgpu::Device,
|
||||
_queue: &wgpu::Queue,
|
||||
) {
|
||||
|
@ -18,7 +18,7 @@ struct Example {
|
||||
|
||||
impl Example {
|
||||
fn create_low_res_target(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
device: &wgpu::Device,
|
||||
bind_group_layout_upscale: &wgpu::BindGroupLayout,
|
||||
) -> (wgpu::TextureView, wgpu::BindGroup) {
|
||||
@ -26,8 +26,8 @@ impl Example {
|
||||
.create_texture(&wgpu::TextureDescriptor {
|
||||
label: Some("Low Resolution Target"),
|
||||
size: wgpu::Extent3d {
|
||||
width: sc_desc.width / 16,
|
||||
height: sc_desc.width / 16,
|
||||
width: config.width / 16,
|
||||
height: config.width / 16,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
@ -73,7 +73,7 @@ impl framework::Example for Example {
|
||||
wgpu::Features::NON_FILL_POLYGON_MODE
|
||||
}
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
_adapter: &wgpu::Adapter,
|
||||
device: &wgpu::Device,
|
||||
_queue: &wgpu::Queue,
|
||||
@ -150,7 +150,7 @@ impl framework::Example for Example {
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader_triangle_and_lines,
|
||||
entry_point: "fs_main_white",
|
||||
targets: &[sc_desc.format.into()],
|
||||
targets: &[config.format.into()],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
polygon_mode: wgpu::PolygonMode::Line,
|
||||
@ -213,7 +213,7 @@ impl framework::Example for Example {
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: "fs_main",
|
||||
targets: &[sc_desc.format.into()],
|
||||
targets: &[config.format.into()],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState::default(),
|
||||
depth_stencil: None,
|
||||
@ -224,7 +224,7 @@ impl framework::Example for Example {
|
||||
};
|
||||
|
||||
let (low_res_target, bind_group_upscale) =
|
||||
Self::create_low_res_target(sc_desc, device, &bind_group_layout_upscale);
|
||||
Self::create_low_res_target(config, device, &bind_group_layout_upscale);
|
||||
|
||||
Self {
|
||||
low_res_target,
|
||||
@ -240,12 +240,12 @@ impl framework::Example for Example {
|
||||
|
||||
fn resize(
|
||||
&mut self,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
device: &wgpu::Device,
|
||||
_queue: &wgpu::Queue,
|
||||
) {
|
||||
let (low_res_target, bind_group_upscale) =
|
||||
Self::create_low_res_target(sc_desc, device, &self.bind_group_layout_upscale);
|
||||
Self::create_low_res_target(config, device, &self.bind_group_layout_upscale);
|
||||
self.low_res_target = low_res_target;
|
||||
self.bind_group_upscale = bind_group_upscale;
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ impl framework::Example for Example {
|
||||
}
|
||||
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
_adapter: &wgpu::Adapter,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
@ -195,7 +195,7 @@ impl framework::Example for Example {
|
||||
);
|
||||
|
||||
// Create other resources
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_total = Self::generate_matrix(config.width as f32 / config.height as f32);
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
let uniform_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Uniform Buffer"),
|
||||
@ -252,7 +252,7 @@ impl framework::Example for Example {
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: "fs_main",
|
||||
targets: &[sc_desc.format.into()],
|
||||
targets: &[config.format.into()],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
cull_mode: Some(wgpu::Face::Back),
|
||||
@ -278,7 +278,7 @@ impl framework::Example for Example {
|
||||
module: &shader,
|
||||
entry_point: "fs_wire",
|
||||
targets: &[wgpu::ColorTargetState {
|
||||
format: sc_desc.format,
|
||||
format: config.format,
|
||||
blend: Some(wgpu::BlendState {
|
||||
color: wgpu::BlendComponent {
|
||||
operation: wgpu::BlendOperation::Add,
|
||||
@ -322,11 +322,11 @@ impl framework::Example for Example {
|
||||
|
||||
fn resize(
|
||||
&mut self,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
_device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
) {
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_total = Self::generate_matrix(config.width as f32 / config.height as f32);
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
queue.write_buffer(&self.uniform_buf, 0, bytemuck::cast_slice(mx_ref));
|
||||
}
|
||||
|
@ -44,14 +44,14 @@ pub trait Example: 'static + Sized {
|
||||
wgpu::Limits::downlevel_defaults() // These downlevel limits will allow the code to run on all possible hardware
|
||||
}
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
adapter: &wgpu::Adapter,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
) -> Self;
|
||||
fn resize(
|
||||
&mut self,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
);
|
||||
@ -137,7 +137,7 @@ async fn setup<E: Example>(title: &str) -> Setup {
|
||||
required_features - adapter_features
|
||||
);
|
||||
|
||||
// Make sure we use the texture resolution limits from the adapter, so we can support images the size of the swapchain.
|
||||
// Make sure we use the texture resolution limits from the adapter, so we can support images the size of the surface.
|
||||
let needed_limits = E::required_limits().using_resolution(adapter.limits());
|
||||
|
||||
let trace_dir = std::env::var("WGPU_TRACE");
|
||||
@ -178,17 +178,17 @@ fn start<E: Example>(
|
||||
}: Setup,
|
||||
) {
|
||||
let spawner = Spawner::new();
|
||||
let mut sc_desc = wgpu::SwapChainDescriptor {
|
||||
let mut config = wgpu::SurfaceConfiguration {
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
|
||||
format: surface.get_preferred_format(&adapter).unwrap(),
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
present_mode: wgpu::PresentMode::Mailbox,
|
||||
};
|
||||
let mut swap_chain = device.create_swap_chain(&surface, &sc_desc);
|
||||
surface.configure(&device, &config);
|
||||
|
||||
log::info!("Initializing the example...");
|
||||
let mut example = E::init(&sc_desc, &adapter, &device, &queue);
|
||||
let mut example = E::init(&config, &adapter, &device, &queue);
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let mut last_update_inst = Instant::now();
|
||||
@ -237,10 +237,10 @@ fn start<E: Example>(
|
||||
..
|
||||
} => {
|
||||
log::info!("Resizing to {:?}", size);
|
||||
sc_desc.width = size.width.max(1);
|
||||
sc_desc.height = size.height.max(1);
|
||||
example.resize(&sc_desc, &device, &queue);
|
||||
swap_chain = device.create_swap_chain(&surface, &sc_desc);
|
||||
config.width = size.width.max(1);
|
||||
config.height = size.height.max(1);
|
||||
example.resize(&config, &device, &queue);
|
||||
surface.configure(&device, &config);
|
||||
}
|
||||
event::Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::KeyboardInput {
|
||||
@ -287,13 +287,13 @@ fn start<E: Example>(
|
||||
}
|
||||
}
|
||||
|
||||
let frame = match swap_chain.get_current_frame() {
|
||||
let frame = match surface.get_current_frame() {
|
||||
Ok(frame) => frame,
|
||||
Err(_) => {
|
||||
swap_chain = device.create_swap_chain(&surface, &sc_desc);
|
||||
swap_chain
|
||||
surface.configure(&device, &config);
|
||||
surface
|
||||
.get_current_frame()
|
||||
.expect("Failed to acquire next swap chain texture!")
|
||||
.expect("Failed to acquire next surface texture!")
|
||||
}
|
||||
};
|
||||
|
||||
@ -430,7 +430,7 @@ pub fn test<E: Example>(mut params: FrameworkRefTest) {
|
||||
});
|
||||
|
||||
let mut example = E::init(
|
||||
&wgpu::SwapChainDescriptor {
|
||||
&wgpu::SurfaceConfiguration {
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||
width: params.width,
|
||||
|
@ -44,7 +44,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
let swapchain_format = adapter.get_swap_chain_preferred_format(&surface).unwrap();
|
||||
let swapchain_format = surface.get_preferred_format(&adapter).unwrap();
|
||||
|
||||
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: None,
|
||||
@ -64,7 +64,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
|
||||
multisample: wgpu::MultisampleState::default(),
|
||||
});
|
||||
|
||||
let mut sc_desc = wgpu::SwapChainDescriptor {
|
||||
let mut config = wgpu::SurfaceConfiguration {
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
format: swapchain_format,
|
||||
width: size.width,
|
||||
@ -72,7 +72,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
|
||||
present_mode: wgpu::PresentMode::Mailbox,
|
||||
};
|
||||
|
||||
let mut swap_chain = device.create_swap_chain(&surface, &sc_desc);
|
||||
surface.configure(&device, &config);
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
// Have the closure take ownership of the resources.
|
||||
@ -86,13 +86,13 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
|
||||
event: WindowEvent::Resized(size),
|
||||
..
|
||||
} => {
|
||||
// Recreate the swap chain with the new size
|
||||
sc_desc.width = size.width;
|
||||
sc_desc.height = size.height;
|
||||
swap_chain = device.create_swap_chain(&surface, &sc_desc);
|
||||
// Reconfigure the surface with the new size
|
||||
config.width = size.width;
|
||||
config.height = size.height;
|
||||
surface.configure(&device, &config);
|
||||
}
|
||||
Event::RedrawRequested(_) => {
|
||||
let frame = swap_chain
|
||||
let frame = surface
|
||||
.get_current_frame()
|
||||
.expect("Failed to acquire next swap chain texture")
|
||||
.output;
|
||||
|
@ -13,8 +13,7 @@ struct ViewportDesc {
|
||||
|
||||
struct Viewport {
|
||||
desc: ViewportDesc,
|
||||
sc_desc: wgpu::SwapChainDescriptor,
|
||||
swap_chain: wgpu::SwapChain,
|
||||
config: wgpu::SurfaceConfiguration,
|
||||
}
|
||||
|
||||
impl ViewportDesc {
|
||||
@ -30,34 +29,29 @@ impl ViewportDesc {
|
||||
fn build(self, adapter: &wgpu::Adapter, device: &wgpu::Device) -> Viewport {
|
||||
let size = self.window.inner_size();
|
||||
|
||||
let sc_desc = wgpu::SwapChainDescriptor {
|
||||
let config = wgpu::SurfaceConfiguration {
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
format: adapter
|
||||
.get_swap_chain_preferred_format(&self.surface)
|
||||
.unwrap(),
|
||||
format: self.surface.get_preferred_format(adapter).unwrap(),
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
present_mode: wgpu::PresentMode::Fifo,
|
||||
};
|
||||
|
||||
let swap_chain = device.create_swap_chain(&self.surface, &sc_desc);
|
||||
self.surface.configure(device, &config);
|
||||
|
||||
Viewport {
|
||||
desc: self,
|
||||
sc_desc,
|
||||
swap_chain,
|
||||
}
|
||||
Viewport { desc: self, config }
|
||||
}
|
||||
}
|
||||
|
||||
impl Viewport {
|
||||
fn resize(&mut self, device: &wgpu::Device, size: winit::dpi::PhysicalSize<u32>) {
|
||||
self.sc_desc.width = size.width;
|
||||
self.sc_desc.height = size.height;
|
||||
self.swap_chain = device.create_swap_chain(&self.desc.surface, &self.sc_desc);
|
||||
self.config.width = size.width;
|
||||
self.config.height = size.height;
|
||||
self.desc.surface.configure(device, &self.config);
|
||||
}
|
||||
fn get_current_frame(&mut self) -> wgpu::SwapChainTexture {
|
||||
self.swap_chain
|
||||
fn get_current_frame(&mut self) -> wgpu::SurfaceTexture {
|
||||
self.desc
|
||||
.surface
|
||||
.get_current_frame()
|
||||
.expect("Failed to acquire next swap chain texture")
|
||||
.output
|
||||
|
@ -203,7 +203,7 @@ impl framework::Example for Example {
|
||||
}
|
||||
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
_adapter: &wgpu::Adapter,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
@ -262,7 +262,7 @@ impl framework::Example for Example {
|
||||
mipmap_filter: wgpu::FilterMode::Linear,
|
||||
..Default::default()
|
||||
});
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_total = Self::generate_matrix(config.width as f32 / config.height as f32);
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
let uniform_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Uniform Buffer"),
|
||||
@ -287,7 +287,7 @@ impl framework::Example for Example {
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: "fs_main",
|
||||
targets: &[sc_desc.format.into()],
|
||||
targets: &[config.format.into()],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleStrip,
|
||||
@ -425,11 +425,11 @@ impl framework::Example for Example {
|
||||
|
||||
fn resize(
|
||||
&mut self,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
_device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
) {
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_total = Self::generate_matrix(config.width as f32 / config.height as f32);
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
queue.write_buffer(&self.uniform_buf, 0, bytemuck::cast_slice(mx_ref));
|
||||
}
|
||||
|
@ -31,13 +31,13 @@ struct Example {
|
||||
vertex_count: u32,
|
||||
sample_count: u32,
|
||||
rebuild_bundle: bool,
|
||||
sc_desc: wgpu::SwapChainDescriptor,
|
||||
config: wgpu::SurfaceConfiguration,
|
||||
}
|
||||
|
||||
impl Example {
|
||||
fn create_bundle(
|
||||
device: &wgpu::Device,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
shader: &wgpu::ShaderModule,
|
||||
pipeline_layout: &wgpu::PipelineLayout,
|
||||
sample_count: u32,
|
||||
@ -60,7 +60,7 @@ impl Example {
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: shader,
|
||||
entry_point: "fs_main",
|
||||
targets: &[sc_desc.format.into()],
|
||||
targets: &[config.format.into()],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::LineList,
|
||||
@ -76,7 +76,7 @@ impl Example {
|
||||
let mut encoder =
|
||||
device.create_render_bundle_encoder(&wgpu::RenderBundleEncoderDescriptor {
|
||||
label: None,
|
||||
color_formats: &[sc_desc.format],
|
||||
color_formats: &[config.format],
|
||||
depth_stencil: None,
|
||||
sample_count,
|
||||
});
|
||||
@ -90,12 +90,12 @@ impl Example {
|
||||
|
||||
fn create_multisampled_framebuffer(
|
||||
device: &wgpu::Device,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
sample_count: u32,
|
||||
) -> wgpu::TextureView {
|
||||
let multisampled_texture_extent = wgpu::Extent3d {
|
||||
width: sc_desc.width,
|
||||
height: sc_desc.height,
|
||||
width: config.width,
|
||||
height: config.height,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
let multisampled_frame_descriptor = &wgpu::TextureDescriptor {
|
||||
@ -103,7 +103,7 @@ impl Example {
|
||||
mip_level_count: 1,
|
||||
sample_count,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: sc_desc.format,
|
||||
format: config.format,
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
label: None,
|
||||
};
|
||||
@ -116,7 +116,7 @@ impl Example {
|
||||
|
||||
impl framework::Example for Example {
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
_adapter: &wgpu::Adapter,
|
||||
device: &wgpu::Device,
|
||||
_queue: &wgpu::Queue,
|
||||
@ -136,7 +136,7 @@ impl framework::Example for Example {
|
||||
});
|
||||
|
||||
let multisampled_framebuffer =
|
||||
Example::create_multisampled_framebuffer(device, sc_desc, sample_count);
|
||||
Example::create_multisampled_framebuffer(device, config, sample_count);
|
||||
|
||||
let mut vertex_data = vec![];
|
||||
|
||||
@ -163,7 +163,7 @@ impl framework::Example for Example {
|
||||
|
||||
let bundle = Example::create_bundle(
|
||||
device,
|
||||
sc_desc,
|
||||
config,
|
||||
&shader,
|
||||
&pipeline_layout,
|
||||
sample_count,
|
||||
@ -180,7 +180,7 @@ impl framework::Example for Example {
|
||||
vertex_count,
|
||||
sample_count,
|
||||
rebuild_bundle: false,
|
||||
sc_desc: sc_desc.clone(),
|
||||
config: config.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,13 +214,13 @@ impl framework::Example for Example {
|
||||
|
||||
fn resize(
|
||||
&mut self,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
device: &wgpu::Device,
|
||||
_queue: &wgpu::Queue,
|
||||
) {
|
||||
self.sc_desc = sc_desc.clone();
|
||||
self.config = config.clone();
|
||||
self.multisampled_framebuffer =
|
||||
Example::create_multisampled_framebuffer(device, sc_desc, self.sample_count);
|
||||
Example::create_multisampled_framebuffer(device, config, self.sample_count);
|
||||
}
|
||||
|
||||
fn render(
|
||||
@ -233,7 +233,7 @@ impl framework::Example for Example {
|
||||
if self.rebuild_bundle {
|
||||
self.bundle = Example::create_bundle(
|
||||
device,
|
||||
&self.sc_desc,
|
||||
&self.config,
|
||||
&self.shader,
|
||||
&self.pipeline_layout,
|
||||
self.sample_count,
|
||||
@ -241,7 +241,7 @@ impl framework::Example for Example {
|
||||
self.vertex_count,
|
||||
);
|
||||
self.multisampled_framebuffer =
|
||||
Example::create_multisampled_framebuffer(device, &self.sc_desc, self.sample_count);
|
||||
Example::create_multisampled_framebuffer(device, &self.config, self.sample_count);
|
||||
self.rebuild_bundle = false;
|
||||
}
|
||||
|
||||
|
@ -187,13 +187,13 @@ impl Example {
|
||||
}
|
||||
|
||||
fn create_depth_texture(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
device: &wgpu::Device,
|
||||
) -> wgpu::TextureView {
|
||||
let depth_texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
size: wgpu::Extent3d {
|
||||
width: sc_desc.width,
|
||||
height: sc_desc.height,
|
||||
width: config.width,
|
||||
height: config.height,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
@ -214,7 +214,7 @@ impl framework::Example for Example {
|
||||
}
|
||||
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
_adapter: &wgpu::Adapter,
|
||||
device: &wgpu::Device,
|
||||
_queue: &wgpu::Queue,
|
||||
@ -578,7 +578,7 @@ impl framework::Example for Example {
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_total = Self::generate_matrix(config.width as f32 / config.height as f32);
|
||||
let forward_uniforms = GlobalUniforms {
|
||||
proj: *mx_total.as_ref(),
|
||||
num_lights: [lights.len() as u32, 0, 0, 0],
|
||||
@ -625,7 +625,7 @@ impl framework::Example for Example {
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: "fs_main",
|
||||
targets: &[sc_desc.format.into()],
|
||||
targets: &[config.format.into()],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
@ -649,7 +649,7 @@ impl framework::Example for Example {
|
||||
}
|
||||
};
|
||||
|
||||
let forward_depth = Self::create_depth_texture(sc_desc, device);
|
||||
let forward_depth = Self::create_depth_texture(config, device);
|
||||
|
||||
Example {
|
||||
entities,
|
||||
@ -670,12 +670,12 @@ impl framework::Example for Example {
|
||||
|
||||
fn resize(
|
||||
&mut self,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
) {
|
||||
// update view-projection matrix
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_total = Self::generate_matrix(config.width as f32 / config.height as f32);
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
queue.write_buffer(
|
||||
&self.forward_pass.uniform_buf,
|
||||
@ -683,7 +683,7 @@ impl framework::Example for Example {
|
||||
bytemuck::cast_slice(mx_ref),
|
||||
);
|
||||
|
||||
self.forward_depth = Self::create_depth_texture(sc_desc, device);
|
||||
self.forward_depth = Self::create_depth_texture(config, device);
|
||||
}
|
||||
|
||||
fn render(
|
||||
|
@ -73,13 +73,13 @@ impl Skybox {
|
||||
const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth24Plus;
|
||||
|
||||
fn create_depth_texture(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
device: &wgpu::Device,
|
||||
) -> wgpu::TextureView {
|
||||
let depth_texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
size: wgpu::Extent3d {
|
||||
width: sc_desc.width,
|
||||
height: sc_desc.height,
|
||||
width: config.width,
|
||||
height: config.height,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
@ -102,7 +102,7 @@ impl framework::Example for Skybox {
|
||||
}
|
||||
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
_adapter: &wgpu::Adapter,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
@ -182,7 +182,7 @@ impl framework::Example for Skybox {
|
||||
});
|
||||
|
||||
let camera = Camera {
|
||||
screen_size: (sc_desc.width, sc_desc.height),
|
||||
screen_size: (config.width, config.height),
|
||||
angle_xz: 0.2,
|
||||
angle_y: 0.2,
|
||||
dist: 30.0,
|
||||
@ -212,7 +212,7 @@ impl framework::Example for Skybox {
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: "fs_sky",
|
||||
targets: &[sc_desc.format.into()],
|
||||
targets: &[config.format.into()],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
front_face: wgpu::FrontFace::Cw,
|
||||
@ -242,7 +242,7 @@ impl framework::Example for Skybox {
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: "fs_entity",
|
||||
targets: &[sc_desc.format.into()],
|
||||
targets: &[config.format.into()],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
front_face: wgpu::FrontFace::Cw,
|
||||
@ -354,7 +354,7 @@ impl framework::Example for Skybox {
|
||||
label: None,
|
||||
});
|
||||
|
||||
let depth_view = Self::create_depth_texture(sc_desc, device);
|
||||
let depth_view = Self::create_depth_texture(config, device);
|
||||
|
||||
Skybox {
|
||||
camera,
|
||||
@ -383,12 +383,12 @@ impl framework::Example for Skybox {
|
||||
|
||||
fn resize(
|
||||
&mut self,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
device: &wgpu::Device,
|
||||
_queue: &wgpu::Queue,
|
||||
) {
|
||||
self.depth_view = Self::create_depth_texture(sc_desc, device);
|
||||
self.camera.screen_size = (sc_desc.width, sc_desc.height);
|
||||
self.depth_view = Self::create_depth_texture(config, device);
|
||||
self.camera.screen_size = (config.width, config.height);
|
||||
}
|
||||
|
||||
fn render(
|
||||
|
@ -85,7 +85,7 @@ impl framework::Example for Example {
|
||||
}
|
||||
}
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
_adapter: &wgpu::Adapter,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
@ -245,7 +245,7 @@ impl framework::Example for Example {
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &fs_module,
|
||||
entry_point: "main",
|
||||
targets: &[sc_desc.format.into()],
|
||||
targets: &[config.format.into()],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
@ -266,7 +266,7 @@ impl framework::Example for Example {
|
||||
}
|
||||
fn resize(
|
||||
&mut self,
|
||||
_sc_desc: &wgpu::SwapChainDescriptor,
|
||||
_sc_desc: &wgpu::SurfaceConfiguration,
|
||||
_device: &wgpu::Device,
|
||||
_queue: &wgpu::Queue,
|
||||
) {
|
||||
|
@ -156,7 +156,7 @@ impl Example {
|
||||
/// Initializes Uniforms and textures.
|
||||
///
|
||||
fn initialize_resources(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
water_uniforms: &wgpu::Buffer,
|
||||
@ -170,7 +170,7 @@ impl Example {
|
||||
terrain_normal,
|
||||
terrain_flipped,
|
||||
water,
|
||||
} = Self::generate_uniforms(sc_desc.width, sc_desc.height);
|
||||
} = Self::generate_uniforms(config.width, config.height);
|
||||
|
||||
// Put the uniforms into buffers on the GPU
|
||||
queue.write_buffer(
|
||||
@ -186,8 +186,8 @@ impl Example {
|
||||
queue.write_buffer(water_uniforms, 0, bytemuck::cast_slice(&[water]));
|
||||
|
||||
let texture_extent = wgpu::Extent3d {
|
||||
width: sc_desc.width,
|
||||
height: sc_desc.height,
|
||||
width: config.width,
|
||||
height: config.height,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
|
||||
@ -197,7 +197,7 @@ impl Example {
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: sc_desc.format,
|
||||
format: config.format,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING
|
||||
| wgpu::TextureUsages::COPY_DST
|
||||
| wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
@ -263,7 +263,7 @@ impl Example {
|
||||
|
||||
impl framework::Example for Example {
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
_adapter: &wgpu::Adapter,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
@ -460,7 +460,7 @@ impl framework::Example for Example {
|
||||
// This puts values behind what was laid out in the bind group layout.
|
||||
|
||||
let (reflect_view, depth_buffer, water_bind_group) = Self::initialize_resources(
|
||||
sc_desc,
|
||||
config,
|
||||
device,
|
||||
queue,
|
||||
&water_uniform_buf,
|
||||
@ -524,7 +524,7 @@ impl framework::Example for Example {
|
||||
// Describes how the colour will be interpolated
|
||||
// and assigned to the output attachment.
|
||||
targets: &[wgpu::ColorTargetState {
|
||||
format: sc_desc.format,
|
||||
format: config.format,
|
||||
blend: Some(wgpu::BlendState {
|
||||
color: wgpu::BlendComponent {
|
||||
src_factor: wgpu::BlendFactor::SrcAlpha,
|
||||
@ -583,7 +583,7 @@ impl framework::Example for Example {
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &terrain_module,
|
||||
entry_point: "fs_main",
|
||||
targets: &[sc_desc.format.into()],
|
||||
targets: &[config.format.into()],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
@ -633,11 +633,11 @@ impl framework::Example for Example {
|
||||
|
||||
fn resize(
|
||||
&mut self,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
) {
|
||||
if sc_desc.width == 0 && sc_desc.height == 0 {
|
||||
if config.width == 0 && config.height == 0 {
|
||||
// Stop rendering altogether.
|
||||
self.active = None;
|
||||
return;
|
||||
@ -647,7 +647,7 @@ impl framework::Example for Example {
|
||||
// Regenerate all of the buffers and textures.
|
||||
|
||||
let (reflect_view, depth_buffer, water_bind_group) = Self::initialize_resources(
|
||||
sc_desc,
|
||||
config,
|
||||
device,
|
||||
queue,
|
||||
&self.water_uniform_buf,
|
||||
|
@ -4,7 +4,7 @@ use crate::{
|
||||
ComputePipelineDescriptor, DownlevelCapabilities, Features, Label, Limits, LoadOp, MapMode,
|
||||
Operations, PipelineLayoutDescriptor, RenderBundleEncoderDescriptor, RenderPipelineDescriptor,
|
||||
SamplerDescriptor, ShaderModuleDescriptor, ShaderModuleDescriptorSpirV, ShaderSource,
|
||||
SwapChainStatus, TextureDescriptor, TextureFormat, TextureViewDescriptor,
|
||||
SurfaceStatus, TextureDescriptor, TextureFormat, TextureViewDescriptor,
|
||||
};
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
@ -675,6 +675,14 @@ fn map_pass_channel<V: Copy + Default>(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Surface {
|
||||
id: wgc::id::SurfaceId,
|
||||
/// Configured device is needed to know which backend
|
||||
/// code to execute when acquiring a new frame.
|
||||
configured_device: Mutex<Option<wgc::id::DeviceId>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Device {
|
||||
id: wgc::id::DeviceId,
|
||||
@ -722,10 +730,9 @@ impl crate::Context for Context {
|
||||
type CommandBufferId = wgc::id::CommandBufferId;
|
||||
type RenderBundleEncoderId = wgc::command::RenderBundleEncoder;
|
||||
type RenderBundleId = wgc::id::RenderBundleId;
|
||||
type SurfaceId = wgc::id::SurfaceId;
|
||||
type SwapChainId = wgc::id::SwapChainId;
|
||||
type SurfaceId = Surface;
|
||||
|
||||
type SwapChainOutputDetail = SwapChainOutputDetail;
|
||||
type SurfaceOutputDetail = SurfaceOutputDetail;
|
||||
|
||||
type RequestAdapterFuture = Ready<Option<Self::AdapterId>>;
|
||||
#[allow(clippy::type_complexity)]
|
||||
@ -745,7 +752,10 @@ impl crate::Context for Context {
|
||||
&self,
|
||||
handle: &impl raw_window_handle::HasRawWindowHandle,
|
||||
) -> Self::SurfaceId {
|
||||
self.0.instance_create_surface(handle, PhantomData)
|
||||
Surface {
|
||||
id: self.0.instance_create_surface(handle, PhantomData),
|
||||
configured_device: Mutex::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn instance_request_adapter(
|
||||
@ -755,7 +765,7 @@ impl crate::Context for Context {
|
||||
let id = self.0.request_adapter(
|
||||
&wgc::instance::RequestAdapterOptions {
|
||||
power_preference: options.power_preference,
|
||||
compatible_surface: options.compatible_surface.map(|surface| surface.id),
|
||||
compatible_surface: options.compatible_surface.map(|surface| surface.id.id),
|
||||
},
|
||||
wgc::instance::AdapterInputs::Mask(wgt::Backends::all(), |_| PhantomData),
|
||||
);
|
||||
@ -801,26 +811,13 @@ impl crate::Context for Context {
|
||||
surface: &Self::SurfaceId,
|
||||
) -> bool {
|
||||
let global = &self.0;
|
||||
match wgc::gfx_select!(adapter => global.adapter_is_surface_supported(*adapter, *surface)) {
|
||||
match wgc::gfx_select!(adapter => global.adapter_is_surface_supported(*adapter, surface.id))
|
||||
{
|
||||
Ok(result) => result,
|
||||
Err(err) => self.handle_error_fatal(err, "Adapter::is_surface_supported"),
|
||||
}
|
||||
}
|
||||
|
||||
fn adapter_get_swap_chain_preferred_format(
|
||||
&self,
|
||||
adapter: &Self::AdapterId,
|
||||
surface: &Self::SurfaceId,
|
||||
) -> Option<TextureFormat> {
|
||||
let global = &self.0;
|
||||
match wgc::gfx_select!(adapter => global.adapter_get_swap_chain_preferred_format(*adapter, *surface))
|
||||
{
|
||||
Ok(swap_chain_preferred_format) => Some(swap_chain_preferred_format),
|
||||
Err(wgc::instance::GetSwapChainPreferredFormatError::UnsupportedQueueFamily) => None,
|
||||
Err(err) => self.handle_error_fatal(err, "Adapter::get_swap_chain_preferred_format"),
|
||||
}
|
||||
}
|
||||
|
||||
fn adapter_features(&self, adapter: &Self::AdapterId) -> Features {
|
||||
let global = &self.0;
|
||||
match wgc::gfx_select!(*adapter => global.adapter_features(*adapter)) {
|
||||
@ -866,6 +863,71 @@ impl crate::Context for Context {
|
||||
}
|
||||
}
|
||||
|
||||
fn surface_get_preferred_format(
|
||||
&self,
|
||||
surface: &Self::SurfaceId,
|
||||
adapter: &Self::AdapterId,
|
||||
) -> Option<TextureFormat> {
|
||||
let global = &self.0;
|
||||
match wgc::gfx_select!(adapter => global.surface_get_preferred_format(surface.id, *adapter))
|
||||
{
|
||||
Ok(format) => Some(format),
|
||||
Err(wgc::instance::GetSurfacePreferredFormatError::UnsupportedQueueFamily) => None,
|
||||
Err(err) => self.handle_error_fatal(err, "Surface::get_preferred_format"),
|
||||
}
|
||||
}
|
||||
|
||||
fn surface_configure(
|
||||
&self,
|
||||
surface: &Self::SurfaceId,
|
||||
device: &Self::DeviceId,
|
||||
config: &wgt::SurfaceConfiguration,
|
||||
) {
|
||||
let global = &self.0;
|
||||
let error =
|
||||
wgc::gfx_select!(device.id => global.surface_configure(surface.id, device.id, config));
|
||||
if let Some(e) = error {
|
||||
self.handle_error_fatal(e, "Surface::configure");
|
||||
} else {
|
||||
*surface.configured_device.lock() = Some(device.id);
|
||||
}
|
||||
}
|
||||
|
||||
fn surface_get_current_texture_view(
|
||||
&self,
|
||||
surface: &Self::SurfaceId,
|
||||
) -> (
|
||||
Option<Self::TextureViewId>,
|
||||
SurfaceStatus,
|
||||
Self::SurfaceOutputDetail,
|
||||
) {
|
||||
let global = &self.0;
|
||||
let device_id = surface
|
||||
.configured_device
|
||||
.lock()
|
||||
.expect("Surface was not configured?");
|
||||
match wgc::gfx_select!(
|
||||
device_id => global.surface_get_current_texture_view(surface.id, PhantomData)
|
||||
) {
|
||||
Ok(wgc::present::SurfaceOutput { status, view_id }) => (
|
||||
view_id,
|
||||
status,
|
||||
SurfaceOutputDetail {
|
||||
surface_id: surface.id,
|
||||
},
|
||||
),
|
||||
Err(err) => self.handle_error_fatal(err, "Surface::get_current_texture_view"),
|
||||
}
|
||||
}
|
||||
|
||||
fn surface_present(&self, view: &Self::TextureViewId, detail: &Self::SurfaceOutputDetail) {
|
||||
let global = &self.0;
|
||||
match wgc::gfx_select!(*view => global.surface_present(detail.surface_id)) {
|
||||
Ok(_status) => (),
|
||||
Err(err) => self.handle_error_fatal(err, "Surface::present"),
|
||||
}
|
||||
}
|
||||
|
||||
fn device_features(&self, device: &Self::DeviceId) -> Features {
|
||||
let global = &self.0;
|
||||
match wgc::gfx_select!(device.id => global.device_features(device.id)) {
|
||||
@ -890,20 +952,6 @@ impl crate::Context for Context {
|
||||
}
|
||||
}
|
||||
|
||||
fn device_create_swap_chain(
|
||||
&self,
|
||||
device: &Self::DeviceId,
|
||||
surface: &Self::SurfaceId,
|
||||
desc: &wgt::SwapChainDescriptor,
|
||||
) -> Self::SwapChainId {
|
||||
let global = &self.0;
|
||||
let (sc, error) = wgc::gfx_select!(device.id => global.device_create_swap_chain(device.id, *surface, desc));
|
||||
match error {
|
||||
Some(e) => self.handle_error_fatal(e, "Device::create_swap_chain"),
|
||||
None => sc,
|
||||
}
|
||||
}
|
||||
|
||||
fn device_create_shader_module(
|
||||
&self,
|
||||
device: &Self::DeviceId,
|
||||
@ -1507,37 +1555,6 @@ impl crate::Context for Context {
|
||||
}
|
||||
}
|
||||
|
||||
fn swap_chain_get_current_texture_view(
|
||||
&self,
|
||||
swap_chain: &Self::SwapChainId,
|
||||
) -> (
|
||||
Option<Self::TextureViewId>,
|
||||
SwapChainStatus,
|
||||
Self::SwapChainOutputDetail,
|
||||
) {
|
||||
let global = &self.0;
|
||||
match wgc::gfx_select!(
|
||||
*swap_chain => global.swap_chain_get_current_texture_view(*swap_chain, PhantomData)
|
||||
) {
|
||||
Ok(wgc::swap_chain::SwapChainOutput { status, view_id }) => (
|
||||
view_id,
|
||||
status,
|
||||
SwapChainOutputDetail {
|
||||
swap_chain_id: *swap_chain,
|
||||
},
|
||||
),
|
||||
Err(err) => self.handle_error_fatal(err, "SwapChain::get_current_texture_view"),
|
||||
}
|
||||
}
|
||||
|
||||
fn swap_chain_present(&self, view: &Self::TextureViewId, detail: &Self::SwapChainOutputDetail) {
|
||||
let global = &self.0;
|
||||
match wgc::gfx_select!(*view => global.swap_chain_present(detail.swap_chain_id)) {
|
||||
Ok(_status) => (),
|
||||
Err(err) => self.handle_error_fatal(err, "SwapChain::present"),
|
||||
}
|
||||
}
|
||||
|
||||
fn texture_create_view(
|
||||
&self,
|
||||
texture: &Self::TextureId,
|
||||
@ -2079,8 +2096,8 @@ impl crate::Context for Context {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct SwapChainOutputDetail {
|
||||
swap_chain_id: wgc::id::SwapChainId,
|
||||
pub(crate) struct SurfaceOutputDetail {
|
||||
surface_id: wgc::id::SurfaceId,
|
||||
}
|
||||
|
||||
type ErrorSink = Arc<Mutex<ErrorSinkRaw>>;
|
||||
|
@ -909,9 +909,8 @@ impl crate::Context for Context {
|
||||
type RenderBundleEncoderId = RenderBundleEncoder;
|
||||
type RenderBundleId = Sendable<web_sys::GpuRenderBundle>;
|
||||
type SurfaceId = Sendable<web_sys::GpuCanvasContext>;
|
||||
type SwapChainId = Sendable<web_sys::GpuSwapChain>;
|
||||
|
||||
type SwapChainOutputDetail = SwapChainOutputDetail;
|
||||
type SurfaceOutputDetail = SurfaceOutputDetail;
|
||||
|
||||
type RequestAdapterFuture = MakeSendFuture<
|
||||
wasm_bindgen_futures::JsFuture,
|
||||
@ -1043,16 +1042,6 @@ impl crate::Context for Context {
|
||||
)
|
||||
}
|
||||
|
||||
fn adapter_get_swap_chain_preferred_format(
|
||||
&self,
|
||||
adapter: &Self::AdapterId,
|
||||
surface: &Self::SurfaceId,
|
||||
) -> Option<wgt::TextureFormat> {
|
||||
let format =
|
||||
map_texture_format_from_web_sys(surface.0.get_swap_chain_preferred_format(&adapter.0));
|
||||
Some(format)
|
||||
}
|
||||
|
||||
fn adapter_features(&self, adapter: &Self::AdapterId) -> wgt::Features {
|
||||
// TODO
|
||||
let _features = adapter.0.features();
|
||||
@ -1112,6 +1101,49 @@ impl crate::Context for Context {
|
||||
format.describe().guaranteed_format_features
|
||||
}
|
||||
|
||||
fn surface_get_preferred_format(
|
||||
&self,
|
||||
surface: &Self::SurfaceId,
|
||||
adapter: &Self::AdapterId,
|
||||
) -> Option<wgt::TextureFormat> {
|
||||
let format =
|
||||
map_texture_format_from_web_sys(surface.0.get_swap_chain_preferred_format(&adapter.0));
|
||||
Some(format)
|
||||
}
|
||||
|
||||
fn surface_configure(
|
||||
&self,
|
||||
surface: &Self::SurfaceId,
|
||||
device: &Self::DeviceId,
|
||||
config: &wgt::SurfaceConfiguration,
|
||||
) {
|
||||
let mut mapped =
|
||||
web_sys::GpuSwapChainDescriptor::new(&device.0, map_texture_format(config.format));
|
||||
mapped.usage(config.usage.bits());
|
||||
surface.0.configure_swap_chain(&mapped);
|
||||
}
|
||||
|
||||
fn surface_get_current_texture_view(
|
||||
&self,
|
||||
_surface: &Self::SurfaceId,
|
||||
) -> (
|
||||
Option<Self::TextureViewId>,
|
||||
wgt::SurfaceStatus,
|
||||
Self::SurfaceOutputDetail,
|
||||
) {
|
||||
// TODO: Should we pass a descriptor here?
|
||||
// Or is the default view always correct?
|
||||
(
|
||||
None, //TODO: surface.0.get_current_texture().create_view()
|
||||
wgt::SurfaceStatus::Good,
|
||||
(),
|
||||
)
|
||||
}
|
||||
|
||||
fn surface_present(&self, _view: &Self::TextureViewId, _detail: &Self::SurfaceOutputDetail) {
|
||||
// Swapchain is presented automatically
|
||||
}
|
||||
|
||||
fn device_features(&self, _device: &Self::DeviceId) -> wgt::Features {
|
||||
// TODO
|
||||
wgt::Features::empty()
|
||||
@ -1127,18 +1159,6 @@ impl crate::Context for Context {
|
||||
wgt::DownlevelCapabilities::default()
|
||||
}
|
||||
|
||||
fn device_create_swap_chain(
|
||||
&self,
|
||||
device: &Self::DeviceId,
|
||||
surface: &Self::SurfaceId,
|
||||
desc: &wgt::SwapChainDescriptor,
|
||||
) -> Self::SwapChainId {
|
||||
let mut mapped =
|
||||
web_sys::GpuSwapChainDescriptor::new(&device.0, map_texture_format(desc.format));
|
||||
mapped.usage(desc.usage.bits());
|
||||
Sendable(surface.0.configure_swap_chain(&mapped))
|
||||
}
|
||||
|
||||
fn device_create_shader_module(
|
||||
&self,
|
||||
device: &Self::DeviceId,
|
||||
@ -1582,31 +1602,6 @@ impl crate::Context for Context {
|
||||
buffer.0.unmap();
|
||||
}
|
||||
|
||||
fn swap_chain_get_current_texture_view(
|
||||
&self,
|
||||
swap_chain: &Self::SwapChainId,
|
||||
) -> (
|
||||
Option<Self::TextureViewId>,
|
||||
wgt::SwapChainStatus,
|
||||
Self::SwapChainOutputDetail,
|
||||
) {
|
||||
// TODO: Should we pass a descriptor here?
|
||||
// Or is the default view always correct?
|
||||
(
|
||||
Some(Sendable(swap_chain.0.get_current_texture().create_view())),
|
||||
wgt::SwapChainStatus::Good,
|
||||
(),
|
||||
)
|
||||
}
|
||||
|
||||
fn swap_chain_present(
|
||||
&self,
|
||||
_view: &Self::TextureViewId,
|
||||
_detail: &Self::SwapChainOutputDetail,
|
||||
) {
|
||||
// Swapchain is presented automatically
|
||||
}
|
||||
|
||||
fn texture_create_view(
|
||||
&self,
|
||||
texture: &Self::TextureId,
|
||||
@ -2047,7 +2042,7 @@ impl crate::Context for Context {
|
||||
fn device_stop_capture(&self, _device: &Self::DeviceId) {}
|
||||
}
|
||||
|
||||
pub(crate) type SwapChainOutputDetail = ();
|
||||
pub(crate) type SurfaceOutputDetail = ();
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BufferMappedRange {
|
||||
|
139
wgpu/src/lib.rs
139
wgpu/src/lib.rs
@ -34,7 +34,7 @@ pub use wgt::{
|
||||
PipelineStatisticsTypes, PolygonMode, PowerPreference, PresentMode, PrimitiveState,
|
||||
PrimitiveTopology, PushConstantRange, QueryType, RenderBundleDepthStencil, SamplerBorderColor,
|
||||
ShaderLocation, ShaderModel, ShaderStages, StencilFaceState, StencilOperation, StencilState,
|
||||
StorageTextureAccess, SwapChainDescriptor, SwapChainStatus, TextureAspect, TextureDimension,
|
||||
StorageTextureAccess, SurfaceConfiguration, SurfaceStatus, TextureAspect, TextureDimension,
|
||||
TextureFormat, TextureFormatFeatureFlags, TextureFormatFeatures, TextureSampleType,
|
||||
TextureUsages, TextureViewDimension, VertexAttribute, VertexFormat, VertexStepMode,
|
||||
BIND_BUFFER_ALIGNMENT, COPY_BUFFER_ALIGNMENT, COPY_BYTES_PER_ROW_ALIGNMENT, MAP_ALIGNMENT,
|
||||
@ -174,9 +174,8 @@ trait Context: Debug + Send + Sized + Sync {
|
||||
type RenderBundleEncoderId: Debug + RenderInner<Self>;
|
||||
type RenderBundleId: Debug + Send + Sync + 'static;
|
||||
type SurfaceId: Debug + Send + Sync + 'static;
|
||||
type SwapChainId: Debug + Send + Sync + 'static;
|
||||
|
||||
type SwapChainOutputDetail: Send;
|
||||
type SurfaceOutputDetail: Send;
|
||||
|
||||
type RequestAdapterFuture: Future<Output = Option<Self::AdapterId>> + Send;
|
||||
type RequestDeviceFuture: Future<Output = Result<(Self::DeviceId, Self::QueueId), RequestDeviceError>>
|
||||
@ -204,11 +203,6 @@ trait Context: Debug + Send + Sized + Sync {
|
||||
adapter: &Self::AdapterId,
|
||||
surface: &Self::SurfaceId,
|
||||
) -> bool;
|
||||
fn adapter_get_swap_chain_preferred_format(
|
||||
&self,
|
||||
adapter: &Self::AdapterId,
|
||||
surface: &Self::SurfaceId,
|
||||
) -> Option<TextureFormat>;
|
||||
fn adapter_features(&self, adapter: &Self::AdapterId) -> Features;
|
||||
fn adapter_limits(&self, adapter: &Self::AdapterId) -> Limits;
|
||||
fn adapter_downlevel_properties(&self, adapter: &Self::AdapterId) -> DownlevelCapabilities;
|
||||
@ -219,15 +213,30 @@ trait Context: Debug + Send + Sized + Sync {
|
||||
format: TextureFormat,
|
||||
) -> TextureFormatFeatures;
|
||||
|
||||
fn surface_get_preferred_format(
|
||||
&self,
|
||||
surface: &Self::SurfaceId,
|
||||
adapter: &Self::AdapterId,
|
||||
) -> Option<TextureFormat>;
|
||||
fn surface_configure(
|
||||
&self,
|
||||
surface: &Self::SurfaceId,
|
||||
device: &Self::DeviceId,
|
||||
config: &SurfaceConfiguration,
|
||||
);
|
||||
fn surface_get_current_texture_view(
|
||||
&self,
|
||||
surface: &Self::SurfaceId,
|
||||
) -> (
|
||||
Option<Self::TextureViewId>,
|
||||
SurfaceStatus,
|
||||
Self::SurfaceOutputDetail,
|
||||
);
|
||||
fn surface_present(&self, view: &Self::TextureViewId, detail: &Self::SurfaceOutputDetail);
|
||||
|
||||
fn device_features(&self, device: &Self::DeviceId) -> Features;
|
||||
fn device_limits(&self, device: &Self::DeviceId) -> Limits;
|
||||
fn device_downlevel_properties(&self, device: &Self::DeviceId) -> DownlevelCapabilities;
|
||||
fn device_create_swap_chain(
|
||||
&self,
|
||||
device: &Self::DeviceId,
|
||||
surface: &Self::SurfaceId,
|
||||
desc: &SwapChainDescriptor,
|
||||
) -> Self::SwapChainId;
|
||||
fn device_create_shader_module(
|
||||
&self,
|
||||
device: &Self::DeviceId,
|
||||
@ -313,15 +322,6 @@ trait Context: Debug + Send + Sized + Sync {
|
||||
sub_range: Range<BufferAddress>,
|
||||
) -> BufferMappedRange;
|
||||
fn buffer_unmap(&self, buffer: &Self::BufferId);
|
||||
fn swap_chain_get_current_texture_view(
|
||||
&self,
|
||||
swap_chain: &Self::SwapChainId,
|
||||
) -> (
|
||||
Option<Self::TextureViewId>,
|
||||
SwapChainStatus,
|
||||
Self::SwapChainOutputDetail,
|
||||
);
|
||||
fn swap_chain_present(&self, view: &Self::TextureViewId, detail: &Self::SwapChainOutputDetail);
|
||||
fn texture_create_view(
|
||||
&self,
|
||||
texture: &Self::TextureId,
|
||||
@ -670,16 +670,6 @@ impl Drop for Surface {
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle to a swap chain.
|
||||
///
|
||||
/// A `SwapChain` represents the image or series of images that will be presented to a [`Surface`].
|
||||
/// A `SwapChain` may be created with [`Device::create_swap_chain`].
|
||||
#[derive(Debug)]
|
||||
pub struct SwapChain {
|
||||
context: Arc<C>,
|
||||
id: <C as Context>::SwapChainId,
|
||||
}
|
||||
|
||||
/// Handle to a binding group layout.
|
||||
///
|
||||
/// A `BindGroupLayout` is a handle to the GPU-side layout of a binding group. It can be used to
|
||||
@ -1337,27 +1327,27 @@ pub struct RenderBundleEncoderDescriptor<'a> {
|
||||
pub sample_count: u32,
|
||||
}
|
||||
|
||||
/// Swap chain image that can be rendered to.
|
||||
/// Surface texture that can be rendered to.
|
||||
#[derive(Debug)]
|
||||
pub struct SwapChainTexture {
|
||||
pub struct SurfaceTexture {
|
||||
/// Accessible view of the frame.
|
||||
pub view: TextureView,
|
||||
detail: <C as Context>::SwapChainOutputDetail,
|
||||
detail: <C as Context>::SurfaceOutputDetail,
|
||||
}
|
||||
|
||||
/// Result of a successful call to [`SwapChain::get_current_frame`].
|
||||
/// Result of a successful call to [`Surface::get_current_frame`].
|
||||
#[derive(Debug)]
|
||||
pub struct SwapChainFrame {
|
||||
pub struct SurfaceFrame {
|
||||
/// The texture into which the next frame should be rendered.
|
||||
pub output: SwapChainTexture,
|
||||
pub output: SurfaceTexture,
|
||||
/// `true` if the acquired buffer can still be used for rendering,
|
||||
/// but should be recreated for maximum performance.
|
||||
pub suboptimal: bool,
|
||||
}
|
||||
|
||||
/// Result of an unsuccessful call to [`SwapChain::get_current_frame`].
|
||||
/// Result of an unsuccessful call to [`Surface::get_current_frame`].
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub enum SwapChainError {
|
||||
pub enum SurfaceError {
|
||||
/// A timeout was encountered while trying to acquire the next frame.
|
||||
Timeout,
|
||||
/// The underlying surface has changed, and therefore the swap chain must be updated.
|
||||
@ -1368,7 +1358,7 @@ pub enum SwapChainError {
|
||||
OutOfMemory,
|
||||
}
|
||||
|
||||
impl Display for SwapChainError {
|
||||
impl Display for SurfaceError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", match self {
|
||||
Self::Timeout => "A timeout was encountered while trying to acquire the next frame",
|
||||
@ -1379,7 +1369,7 @@ impl Display for SwapChainError {
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for SwapChainError {}
|
||||
impl error::Error for SurfaceError {}
|
||||
|
||||
impl Instance {
|
||||
/// Create an new instance of wgpu.
|
||||
@ -1574,13 +1564,6 @@ impl Adapter {
|
||||
Context::adapter_is_surface_supported(&*self.context, &self.id, &surface.id)
|
||||
}
|
||||
|
||||
/// Returns an optimal texture format to use for the [`SwapChain`] with this adapter.
|
||||
///
|
||||
/// Returns None if the surface is incompatible with the adapter.
|
||||
pub fn get_swap_chain_preferred_format(&self, surface: &Surface) -> Option<TextureFormat> {
|
||||
Context::adapter_get_swap_chain_preferred_format(&*self.context, &self.id, &surface.id)
|
||||
}
|
||||
|
||||
/// List all features that are supported with this adapter.
|
||||
///
|
||||
/// Features must be explicitly requested in [`Adapter::request_device`] in order
|
||||
@ -1794,19 +1777,6 @@ impl Device {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new [`SwapChain`] which targets `surface`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - A old [`SwapChainFrame`] is still alive referencing an old swapchain.
|
||||
/// - Texture format requested is unsupported on the swap chain.
|
||||
pub fn create_swap_chain(&self, surface: &Surface, desc: &SwapChainDescriptor) -> SwapChain {
|
||||
SwapChain {
|
||||
context: Arc::clone(&self.context),
|
||||
id: Context::device_create_swap_chain(&*self.context, &self.id, &surface.id, desc),
|
||||
}
|
||||
}
|
||||
|
||||
/// Set a callback for errors that are not handled in error scopes.
|
||||
pub fn on_uncaptured_error(&self, handler: impl UncapturedErrorHandler) {
|
||||
self.context.device_on_uncaptured_error(&self.id, handler);
|
||||
@ -3083,26 +3053,43 @@ impl Queue {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for SwapChainTexture {
|
||||
impl Drop for SurfaceTexture {
|
||||
fn drop(&mut self) {
|
||||
if !thread::panicking() {
|
||||
Context::swap_chain_present(&*self.view.context, &self.view.id, &self.detail);
|
||||
Context::surface_present(&*self.view.context, &self.view.id, &self.detail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SwapChain {
|
||||
impl Surface {
|
||||
/// Returns an optimal texture format to use for the [`Surface`] with this adapter.
|
||||
///
|
||||
/// Returns None if the surface is incompatible with the adapter.
|
||||
pub fn get_preferred_format(&self, adapter: &Adapter) -> Option<TextureFormat> {
|
||||
Context::surface_get_preferred_format(&*self.context, &self.id, &adapter.id)
|
||||
}
|
||||
|
||||
/// Initializes [`Surface`] for presentation.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - A old [`SurfaceFrame`] is still alive referencing an old surface.
|
||||
/// - Texture format requested is unsupported on the surface.
|
||||
pub fn configure(&self, device: &Device, config: &SurfaceConfiguration) {
|
||||
Context::surface_configure(&*self.context, &self.id, &device.id, config)
|
||||
}
|
||||
|
||||
/// Returns the next texture to be presented by the swapchain for drawing.
|
||||
///
|
||||
/// When the [`SwapChainFrame`] returned by this method is dropped, the swapchain will present
|
||||
/// When the [`SurfaceFrame`] returned by this method is dropped, the swapchain will present
|
||||
/// the texture to the associated [`Surface`].
|
||||
///
|
||||
/// If a SwapChainFrame referencing this surface is alive when the swapchain is recreated,
|
||||
/// If a SurfaceFrame referencing this surface is alive when the swapchain is recreated,
|
||||
/// recreating the swapchain will panic.
|
||||
pub fn get_current_frame(&self) -> Result<SwapChainFrame, SwapChainError> {
|
||||
pub fn get_current_frame(&self) -> Result<SurfaceFrame, SurfaceError> {
|
||||
let (view_id, status, detail) =
|
||||
Context::swap_chain_get_current_texture_view(&*self.context, &self.id);
|
||||
let output = view_id.map(|id| SwapChainTexture {
|
||||
Context::surface_get_current_texture_view(&*self.context, &self.id);
|
||||
let output = view_id.map(|id| SurfaceTexture {
|
||||
view: TextureView {
|
||||
context: Arc::clone(&self.context),
|
||||
id,
|
||||
@ -3112,17 +3099,17 @@ impl SwapChain {
|
||||
});
|
||||
|
||||
match status {
|
||||
SwapChainStatus::Good => Ok(SwapChainFrame {
|
||||
SurfaceStatus::Good => Ok(SurfaceFrame {
|
||||
output: output.unwrap(),
|
||||
suboptimal: false,
|
||||
}),
|
||||
SwapChainStatus::Suboptimal => Ok(SwapChainFrame {
|
||||
SurfaceStatus::Suboptimal => Ok(SurfaceFrame {
|
||||
output: output.unwrap(),
|
||||
suboptimal: true,
|
||||
}),
|
||||
SwapChainStatus::Timeout => Err(SwapChainError::Timeout),
|
||||
SwapChainStatus::Outdated => Err(SwapChainError::Outdated),
|
||||
SwapChainStatus::Lost => Err(SwapChainError::Lost),
|
||||
SurfaceStatus::Timeout => Err(SurfaceError::Timeout),
|
||||
SurfaceStatus::Outdated => Err(SurfaceError::Outdated),
|
||||
SurfaceStatus::Lost => Err(SurfaceError::Lost),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user