Skip to content

Commit

Permalink
Expose alpha_mode, support non-opaque mode on metal and vk backends (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
jinleili committed Sep 19, 2022
1 parent d1c94d0 commit 44399bb
Show file tree
Hide file tree
Showing 20 changed files with 254 additions and 115 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Expand Up @@ -56,9 +56,23 @@ the same every time it is rendered, we now warn if it is missing.
+fn vert_main(v_in: VertexInput) -> @builtin(position) @invariant vec4<f32> {...}
```

#### Alpha Mode

Surface supports `alpha_mode` now. When alpha_mode is equal to `PreMultiplied` or `PostMultiplied`,
the alpha channel of framebuffer is respected in the compositing process, but which mode is available depends on
the different API and `Device`. If don't care about alpha_mode, you can set it to `Auto`.

```diff
SurfaceConfiguration {
// ...
+ alpha_mode: surface.get_supported_alpha_modes(&adapter)[0],
}
```

### Added/New Features

- Add `Buffer::size()` and `Buffer::usage()`; by @kpreid in [#2923](https://github.com/gfx-rs/wgpu/pull/2923)
- Expose `alpha_mode` on SurfaceConfiguration, by @jinleili in [#2836](https://github.com/gfx-rs/wgpu/pull/2836)

### Bug Fixes

Expand Down
99 changes: 79 additions & 20 deletions wgpu-core/src/device/mod.rs
Expand Up @@ -7,7 +7,8 @@ use crate::{
BufferInitTracker, BufferInitTrackerAction, MemoryInitKind, TextureInitRange,
TextureInitTracker, TextureInitTrackerAction,
},
instance, pipeline, present,
instance::{self, Adapter, Surface},
pipeline, present,
resource::{self, BufferMapState},
resource::{BufferAccessError, BufferMapAsyncStatus, BufferMapOperation},
track::{BindGroupStates, TextureSelector, Tracker},
Expand Down Expand Up @@ -681,7 +682,7 @@ impl<A: HalApi> Device<A> {
fn create_texture(
&self,
self_id: id::DeviceId,
adapter: &crate::instance::Adapter<A>,
adapter: &Adapter<A>,
desc: &resource::TextureDescriptor,
) -> Result<resource::Texture<A>, resource::CreateTextureError> {
use resource::{CreateTextureError, TextureDimensionError};
Expand Down Expand Up @@ -2443,7 +2444,7 @@ impl<A: HalApi> Device<A> {
fn create_render_pipeline<G: GlobalIdentityHandlerFactory>(
&self,
self_id: id::DeviceId,
adapter: &crate::instance::Adapter<A>,
adapter: &Adapter<A>,
desc: &pipeline::RenderPipelineDescriptor,
implicit_context: Option<ImplicitPipelineContext>,
hub: &Hub<A, G>,
Expand Down Expand Up @@ -2930,7 +2931,7 @@ impl<A: HalApi> Device<A> {

fn describe_format_features(
&self,
adapter: &crate::instance::Adapter<A>,
adapter: &Adapter<A>,
format: TextureFormat,
) -> Result<wgt::TextureFormatFeatures, MissingFeatures> {
let format_desc = format.describe();
Expand Down Expand Up @@ -3151,32 +3152,56 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.map_err(|_| instance::IsSurfaceSupportedError::InvalidSurface)?;
Ok(adapter.is_surface_supported(surface))
}

pub fn surface_get_supported_formats<A: HalApi>(
&self,
surface_id: id::SurfaceId,
adapter_id: id::AdapterId,
) -> Result<Vec<TextureFormat>, instance::GetSurfaceSupportError> {
profiling::scope!("Surface::get_supported_formats");
let hub = A::hub(self);
let mut token = Token::root();
self.fetch_adapter_and_surface::<A, _, Vec<TextureFormat>>(
surface_id,
adapter_id,
|adapter, surface| surface.get_supported_formats(adapter),
)
}

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::GetSurfaceSupportError::InvalidAdapter)?;
let surface = surface_guard
.get(surface_id)
.map_err(|_| instance::GetSurfaceSupportError::InvalidSurface)?;
pub fn surface_get_supported_present_modes<A: HalApi>(
&self,
surface_id: id::SurfaceId,
adapter_id: id::AdapterId,
) -> Result<Vec<wgt::PresentMode>, instance::GetSurfaceSupportError> {
profiling::scope!("Surface::get_supported_present_modes");
self.fetch_adapter_and_surface::<A, _, Vec<wgt::PresentMode>>(
surface_id,
adapter_id,
|adapter, surface| surface.get_supported_present_modes(adapter),
)
}

surface.get_supported_formats(adapter)
pub fn surface_get_supported_alpha_modes<A: HalApi>(
&self,
surface_id: id::SurfaceId,
adapter_id: id::AdapterId,
) -> Result<Vec<wgt::CompositeAlphaMode>, instance::GetSurfaceSupportError> {
profiling::scope!("Surface::get_supported_alpha_modes");
self.fetch_adapter_and_surface::<A, _, Vec<wgt::CompositeAlphaMode>>(
surface_id,
adapter_id,
|adapter, surface| surface.get_supported_alpha_modes(adapter),
)
}
pub fn surface_get_supported_modes<A: HalApi>(

fn fetch_adapter_and_surface<
A: HalApi,
F: FnOnce(&Adapter<A>, &Surface) -> Result<B, instance::GetSurfaceSupportError>,
B,
>(
&self,
surface_id: id::SurfaceId,
adapter_id: id::AdapterId,
) -> Result<Vec<wgt::PresentMode>, instance::GetSurfaceSupportError> {
profiling::scope!("Surface::get_supported_modes");
get_supported_callback: F,
) -> Result<B, instance::GetSurfaceSupportError> {
let hub = A::hub(self);
let mut token = Token::root();

Expand All @@ -3189,7 +3214,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.get(surface_id)
.map_err(|_| instance::GetSurfaceSupportError::InvalidSurface)?;

surface.get_supported_modes(adapter)
get_supported_callback(adapter, surface)
}

pub fn device_features<A: HalApi>(
Expand Down Expand Up @@ -5070,6 +5095,40 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
available: caps.formats.clone(),
});
}
if !caps
.composite_alpha_modes
.contains(&config.composite_alpha_mode)
{
let new_alpha_mode = 'b: loop {
// Automatic alpha mode checks.
let fallbacks = match config.composite_alpha_mode {
wgt::CompositeAlphaMode::Auto => &[
wgt::CompositeAlphaMode::Opaque,
wgt::CompositeAlphaMode::Inherit,
][..],
_ => {
return Err(E::UnsupportedAlphaMode {
requested: config.composite_alpha_mode,
available: caps.composite_alpha_modes.clone(),
});
}
};

for &fallback in fallbacks {
if caps.composite_alpha_modes.contains(&fallback) {
break 'b fallback;
}
}

unreachable!("Fallback system failed to choose alpha mode. This is a bug. AlphaMode: {:?}, Options: {:?}", config.composite_alpha_mode, &caps.composite_alpha_modes);
};

log::info!(
"Automatically choosing alpha mode by rule {:?}. Chose {new_alpha_mode:?}",
config.composite_alpha_mode
);
config.composite_alpha_mode = new_alpha_mode;
}
if !caps.usage.contains(config.usage) {
return Err(E::UnsupportedUsage);
}
Expand Down Expand Up @@ -5119,7 +5178,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let mut hal_config = hal::SurfaceConfiguration {
swap_chain_size: num_frames,
present_mode: config.present_mode,
composite_alpha_mode: hal::CompositeAlphaMode::Opaque,
composite_alpha_mode: config.alpha_mode,
format: config.format,
extent: wgt::Extent3d {
width: config.width,
Expand Down
41 changes: 24 additions & 17 deletions wgpu-core/src/instance.rs
Expand Up @@ -8,7 +8,7 @@ use crate::{

use wgt::{Backend, Backends, PowerPreference};

use hal::{Adapter as _, Instance as _};
use hal::{Adapter as _, Instance as _, SurfaceCapabilities};
use thiserror::Error;

pub type RequestAdapterOptions = wgt::RequestAdapterOptions<SurfaceId>;
Expand Down Expand Up @@ -156,37 +156,44 @@ impl Surface {
&self,
adapter: &Adapter<A>,
) -> Result<Vec<wgt::TextureFormat>, GetSurfaceSupportError> {
let suf = A::get_surface(self);
let mut caps = unsafe {
profiling::scope!("surface_capabilities");
adapter
.raw
.adapter
.surface_capabilities(&suf.raw)
.ok_or(GetSurfaceSupportError::UnsupportedQueueFamily)?
};
self.get_capabilities(adapter).map(|mut caps| {
// TODO: maybe remove once we support texture view changing srgb-ness
caps.formats.sort_by_key(|f| !f.describe().srgb);
caps.formats
})
}

// TODO: maybe remove once we support texture view changing srgb-ness
caps.formats.sort_by_key(|f| !f.describe().srgb);
pub fn get_supported_present_modes<A: HalApi>(
&self,
adapter: &Adapter<A>,
) -> Result<Vec<wgt::PresentMode>, GetSurfaceSupportError> {
self.get_capabilities(adapter)
.map(|caps| caps.present_modes)
}

Ok(caps.formats)
pub fn get_supported_alpha_modes<A: HalApi>(
&self,
adapter: &Adapter<A>,
) -> Result<Vec<wgt::CompositeAlphaMode>, GetSurfaceSupportError> {
self.get_capabilities(adapter)
.map(|caps| caps.composite_alpha_modes)
}

pub fn get_supported_modes<A: HalApi>(
fn get_capabilities<A: HalApi>(
&self,
adapter: &Adapter<A>,
) -> Result<Vec<wgt::PresentMode>, GetSurfaceSupportError> {
) -> Result<SurfaceCapabilities, GetSurfaceSupportError> {
let suf = A::get_surface(self);
profiling::scope!("surface_capabilities");
let caps = unsafe {
profiling::scope!("surface_capabilities");
adapter
.raw
.adapter
.surface_capabilities(&suf.raw)
.ok_or(GetSurfaceSupportError::UnsupportedQueueFamily)?
};

Ok(caps.present_modes)
Ok(caps)
}
}

Expand Down
5 changes: 5 additions & 0 deletions wgpu-core/src/present.rs
Expand Up @@ -80,6 +80,11 @@ pub enum ConfigureSurfaceError {
requested: wgt::PresentMode,
available: Vec<wgt::PresentMode>,
},
#[error("requested alpha mode {requested:?} is not in the list of supported alpha modes: {available:?}")]
UnsupportedAlphaMode {
requested: wgt::CompositeAlphaMode,
available: Vec<wgt::CompositeAlphaMode>,
},
#[error("requested usage is not supported")]
UnsupportedUsage,
}
Expand Down
2 changes: 1 addition & 1 deletion wgpu-hal/examples/halmark/main.rs
Expand Up @@ -122,7 +122,7 @@ impl<A: hal::Api> Example<A> {
.max(*surface_caps.swap_chain_sizes.start())
.min(*surface_caps.swap_chain_sizes.end()),
present_mode: wgt::PresentMode::Fifo,
composite_alpha_mode: hal::CompositeAlphaMode::Opaque,
composite_alpha_mode: wgt::CompositeAlphaMode::Opaque,
format: wgt::TextureFormat::Bgra8UnormSrgb,
extent: wgt::Extent3d {
width: window_size.0,
Expand Down
9 changes: 2 additions & 7 deletions wgpu-hal/src/auxil/dxgi/conv.rs
Expand Up @@ -177,11 +177,6 @@ pub fn map_vertex_format(format: wgt::VertexFormat) -> dxgiformat::DXGI_FORMAT {
}
}

pub fn map_acomposite_alpha_mode(mode: crate::CompositeAlphaMode) -> native::AlphaMode {
use crate::CompositeAlphaMode as Cam;
match mode {
Cam::Opaque => native::AlphaMode::Ignore,
Cam::PreMultiplied => native::AlphaMode::Premultiplied,
Cam::PostMultiplied => native::AlphaMode::Straight,
}
pub fn map_acomposite_alpha_mode(_mode: wgt::CompositeAlphaMode) -> native::AlphaMode {
native::AlphaMode::Ignore
}
6 changes: 1 addition & 5 deletions wgpu-hal/src/dx12/adapter.rs
Expand Up @@ -488,11 +488,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
| crate::TextureUses::COPY_SRC
| crate::TextureUses::COPY_DST,
present_modes,
composite_alpha_modes: vec![
crate::CompositeAlphaMode::Opaque,
crate::CompositeAlphaMode::PreMultiplied,
crate::CompositeAlphaMode::PostMultiplied,
],
composite_alpha_modes: vec![wgt::CompositeAlphaMode::Opaque],
})
}
}
2 changes: 1 addition & 1 deletion wgpu-hal/src/dx12/device.rs
Expand Up @@ -671,7 +671,7 @@ impl crate::Device<super::Api> for super::Device {
allocator,
device: self.raw,
shared: Arc::clone(&self.shared),
null_rtv_handle: self.null_rtv_handle.clone(),
null_rtv_handle: self.null_rtv_handle,
list: None,
free_lists: Vec::new(),
pass: super::PassState::new(),
Expand Down
2 changes: 1 addition & 1 deletion wgpu-hal/src/gles/adapter.rs
Expand Up @@ -780,7 +780,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
]
},
present_modes: vec![wgt::PresentMode::Fifo], //TODO
composite_alpha_modes: vec![crate::CompositeAlphaMode::Opaque], //TODO
composite_alpha_modes: vec![wgt::CompositeAlphaMode::Opaque], //TODO
swap_chain_sizes: 2..=2,
current_extent: None,
extents: wgt::Extent3d {
Expand Down

0 comments on commit 44399bb

Please sign in to comment.