891: Add AddressMode::ClampToBorder behind a feature r=kvark a=jshrake

**Connections**
Closes #890 
Linked to https://github.com/gfx-rs/wgpu-rs/pull/526

**Description**
- Adds support for border sampler addressing behind a new feature Features::ADDRESS_MODE_CLAMP_TO_BORDER.
- Adds a new enum SamplerBorderColor so that users can optionally specify a supported border color on the SamplerDescriptor.

**Testing**
Tested against the Metal (MacOS 10.15) and Vulkan (Ubuntu 18.04) backends.

Ran the wgpu-rs/cube example and switched the address modes to AddressMode::ClampToBorder, without enabling the feature, and confirmed I received an error message. Ran the same example with the new feature specified in the optional_features return and confirmed that the example ran and looks reasonable.

Co-authored-by: Justin Shrake <justinshrake@gmail.com>
This commit is contained in:
bors[bot] 2020-08-22 21:46:19 +00:00 committed by GitHub
commit 0bb6bb8647
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 62 additions and 1 deletions

View File

@ -759,6 +759,7 @@ pub fn map_wrap(address: wgt::AddressMode) -> hal::image::WrapMode {
Am::ClampToEdge => W::Clamp,
Am::Repeat => W::Tile,
Am::MirrorRepeat => W::Mirror,
Am::ClampToBorder => W::Border,
}
}

View File

@ -1490,6 +1490,19 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.get(device_id)
.map_err(|_| DeviceError::Invalid)?;
let clamp_to_border_enabled = device
.features
.contains(wgt::Features::ADDRESS_MODE_CLAMP_TO_BORDER);
let clamp_to_border_found = desc
.address_modes
.iter()
.any(|am| am == &wgt::AddressMode::ClampToBorder);
if clamp_to_border_found && !clamp_to_border_enabled {
return Err(resource::CreateSamplerError::MissingFeature(
wgt::Features::ADDRESS_MODE_CLAMP_TO_BORDER,
));
}
let actual_clamp = if let Some(clamp) = desc.anisotropy_clamp {
let clamp = clamp.get();
let valid_clamp = clamp <= MAX_ANISOTROPY && conv::is_power_of_two(clamp as u32);
@ -1505,6 +1518,16 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
None
};
let actual_border = desc
.border_color
.map(|c| match c {
wgt::SamplerBorderColor::TransparentBlack => [0.0, 0.0, 0.0, 0.0],
wgt::SamplerBorderColor::OpaqueBlack => [0.0, 0.0, 0.0, 1.0],
wgt::SamplerBorderColor::OpaqueWhite => [1.0, 1.0, 1.0, 1.0],
})
.map(hal::image::PackedColor::from)
.unwrap_or(hal::image::PackedColor(0));
let info = hal::image::SamplerDesc {
min_filter: conv::map_filter(desc.min_filter),
mag_filter: conv::map_filter(desc.mag_filter),
@ -1517,7 +1540,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
lod_bias: hal::image::Lod(0.0),
lod_range: hal::image::Lod(desc.lod_min_clamp)..hal::image::Lod(desc.lod_max_clamp),
comparison: desc.compare.map(conv::map_compare_function),
border: hal::image::PackedColor(0),
border: actual_border,
normalized: true,
anisotropy_clamp: actual_clamp,
};

View File

@ -154,6 +154,9 @@ impl<B: hal::Backend> Adapter<B> {
wgt::Features::MULTI_DRAW_INDIRECT_COUNT,
adapter_features.contains(hal::Features::DRAW_INDIRECT_COUNT),
);
#[cfg(not(target_os = "ios"))]
//TODO: https://github.com/gfx-rs/gfx/issues/3346
features.set(wgt::Features::ADDRESS_MODE_CLAMP_TO_BORDER, true);
let adapter_limits = raw.physical_device.limits();

View File

@ -362,6 +362,8 @@ pub struct SamplerDescriptor<'a> {
pub compare: Option<wgt::CompareFunction>,
/// Valid values: 1, 2, 4, 8, and 16.
pub anisotropy_clamp: Option<NonZeroU8>,
/// Border color to use when address_mode is [`AddressMode::ClampToBorder`]
pub border_color: Option<wgt::SamplerBorderColor>,
}
impl Default for SamplerDescriptor<'_> {
@ -376,6 +378,7 @@ impl Default for SamplerDescriptor<'_> {
lod_max_clamp: std::f32::MAX,
compare: None,
anisotropy_clamp: None,
border_color: None,
}
}
}
@ -397,6 +400,9 @@ pub enum CreateSamplerError {
InvalidClamp(u8),
#[error("cannot create any more samplers")]
TooManyObjects,
/// AddressMode::ClampToBorder requires feature ADDRESS_MODE_CLAMP_TO_BORDER
#[error("Feature {0:?} must be enabled")]
MissingFeature(wgt::Features),
}
impl<B: hal::Backend> Borrow<RefCount> for Sampler<B> {

View File

@ -279,6 +279,17 @@ bitflags::bitflags! {
///
/// This is a native only feature.
const PUSH_CONSTANTS = 0x0000_0000_0080_0000;
/// Allows the use of [`AddressMode::ClampToBorder`].
///
/// Supported platforms:
/// - DX12
/// - Vulkan
/// - Metal (macOS 10.12+ only)
/// - DX11
/// - OpenGL
///
/// This is a web and native feature.
const ADDRESS_MODE_CLAMP_TO_BORDER = 0x0000_0000_0100_0000;
/// Features which are part of the upstream WebGPU standard.
const ALL_WEBGPU = 0x0000_0000_0000_FFFF;
/// Features that are only available when targeting native (not web).
@ -1476,6 +1487,12 @@ pub enum AddressMode {
/// -0.25 -> 0.25
/// 1.25 -> 0.75
MirrorRepeat = 2,
/// Clamp the value to the border of the texture
/// Requires feature [`Features::ADDRESS_MODE_CLAMP_TO_BORDER`]
///
/// -0.25 -> border
/// 1.25 -> border
ClampToBorder = 3,
}
impl Default for AddressMode {
@ -1821,3 +1838,14 @@ pub struct TextureCopyView<T> {
/// The base texel of the texture in the selected `mip_level`.
pub origin: Origin3d,
}
/// Color variation to use when sampler addressing mode is [`AddressMode::ClampToBorder`]
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub enum SamplerBorderColor {
TransparentBlack,
OpaqueBlack,
OpaqueWhite,
}