Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose alpha_mode, support non-opaque mode on metal and vk backends #2836

Merged
merged 6 commits into from Sep 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 @@ -117,7 +117,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