Implement anisotropic filtering and extensions/limits

This commit is contained in:
Connor Fitzgerald
2020-05-31 03:33:55 -04:00
parent 1a569ebe89
commit 415ce97415
4 changed files with 89 additions and 4 deletions

View File

@@ -429,7 +429,7 @@ fn checked_u32_as_u16(value: u32) -> u16 {
value as u16
}
fn is_power_of_two(val: u32) -> bool {
pub fn is_power_of_two(val: u32) -> bool {
val != 0 && (val & (val - 1)) == 0
}

View File

@@ -55,6 +55,7 @@ fn own_label(label: &Label) -> String {
pub const MAX_COLOR_TARGETS: usize = 4;
pub const MAX_MIP_LEVELS: usize = 16;
pub const MAX_VERTEX_BUFFERS: usize = 16;
pub const MAX_ANISOTROPY: u8 = 16;
pub fn all_buffer_stages() -> hal::pso::PipelineStage {
use hal::pso::PipelineStage as Ps;
@@ -541,6 +542,24 @@ impl<B: hal::Backend> Device<B> {
}
impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn device_extensions<B: GfxBackend>(&self, device_id: id::DeviceId) -> wgt::Extensions {
let hub = B::hub(self);
let mut token = Token::root();
let (device_guard, _) = hub.devices.read(&mut token);
let device = &device_guard[device_id];
device.extensions.clone()
}
pub fn device_limits<B: GfxBackend>(&self, device_id: id::DeviceId) -> wgt::Limits {
let hub = B::hub(self);
let mut token = Token::root();
let (device_guard, _) = hub.devices.read(&mut token);
let device = &device_guard[device_id];
device.limits.clone()
}
pub fn device_create_buffer<B: GfxBackend>(
&self,
device_id: id::DeviceId,
@@ -977,6 +996,19 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let (device_guard, mut token) = hub.devices.read(&mut token);
let device = &device_guard[device_id];
if desc.anisotropy_clamp > 1 {
assert!(
device.extensions.anisotropic_filtering,
"Anisotropic clamp may only be used when the anisotropic filtering extension is enabled"
);
let valid_clamp = desc.anisotropy_clamp <= MAX_ANISOTROPY
&& conv::is_power_of_two(desc.anisotropy_clamp as u32);
assert!(
valid_clamp,
"Anisotropic clamp must be one of the values: 0, 1, 2, 4, 8, or 16"
);
}
let info = hal::image::SamplerDesc {
min_filter: conv::map_filter(desc.min_filter),
mag_filter: conv::map_filter(desc.mag_filter),
@@ -991,7 +1023,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
comparison: conv::map_compare_function(desc.compare),
border: hal::image::PackedColor(0),
normalized: true,
anisotropy_clamp: None, //TODO
anisotropy_clamp: if desc.anisotropy_clamp > 1 {
Some(desc.anisotropy_clamp)
} else {
None
},
};
let sampler = resource::Sampler {

View File

@@ -7,7 +7,7 @@ use crate::{
device::Device,
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Input, Token},
id::{AdapterId, DeviceId, SurfaceId},
power, LifeGuard, Stored,
power, LifeGuard, Stored, MAX_BIND_GROUPS,
};
use wgt::{Backend, BackendBit, DeviceDescriptor, PowerPreference, BIND_BUFFER_ALIGNMENT};
@@ -527,6 +527,32 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
AdapterInfo::from_gfx(adapter.raw.info.clone(), adapter_id.backend())
}
pub fn adapter_extensions<B: GfxBackend>(&self, adapter_id: AdapterId) -> wgt::Extensions {
let hub = B::hub(self);
let mut token = Token::root();
let (adapter_guard, _) = hub.adapters.read(&mut token);
let adapter = &adapter_guard[adapter_id];
let features = adapter.raw.physical_device.features();
wgt::Extensions {
anisotropic_filtering: features.contains(hal::Features::SAMPLER_ANISOTROPY),
}
}
pub fn adapter_limits<B: GfxBackend>(&self, adapter_id: AdapterId) -> wgt::Limits {
let hub = B::hub(self);
let mut token = Token::root();
let (adapter_guard, _) = hub.adapters.read(&mut token);
let adapter = &adapter_guard[adapter_id];
let limits = adapter.raw.physical_device.limits();
wgt::Limits {
max_bind_groups: (limits.max_bound_descriptor_sets as u32).min(MAX_BIND_GROUPS as u32),
}
}
pub fn adapter_destroy<B: GfxBackend>(&self, adapter_id: AdapterId) {
let hub = B::hub(self);
let mut token = Token::root();
@@ -560,10 +586,14 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let (adapter_guard, _) = hub.adapters.read(&mut token);
let adapter = &adapter_guard[adapter_id];
let phd = &adapter.raw.physical_device;
let available_features = adapter.raw.physical_device.features();
// Check features that are always needed
let wishful_features = hal::Features::VERTEX_STORES_AND_ATOMICS
| hal::Features::FRAGMENT_STORES_AND_ATOMICS
| hal::Features::NDC_Y_UP;
let enabled_features = adapter.raw.physical_device.features() & wishful_features;
let mut enabled_features = available_features & wishful_features;
if enabled_features != wishful_features {
log::warn!(
"Missing features: {:?}",
@@ -571,6 +601,15 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
);
}
// Check features needed by extensions
if desc.extensions.anisotropic_filtering {
assert!(
available_features.contains(hal::Features::SAMPLER_ANISOTROPY),
"Missing feature SAMPLER_ANISOTROPY for anisotropic filtering extension"
);
enabled_features |= hal::Features::SAMPLER_ANISOTROPY;
}
let family = adapter
.raw
.queue_families

View File

@@ -88,6 +88,10 @@ impl From<Backend> for BackendBit {
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct Extensions {
/// This is a native only extension. Support is planned to be added to webgpu,
/// but it is not yet implemented.
///
/// https://github.com/gpuweb/gpuweb/issues/696
pub anisotropic_filtering: bool,
}
@@ -926,6 +930,11 @@ pub struct SamplerDescriptor<L> {
pub lod_min_clamp: f32,
pub lod_max_clamp: f32,
pub compare: CompareFunction,
/// Anisotropic filtering extension must be enabled if this value is
/// anything other than 0 and 1.
///
/// Valid values are 0, 1, 2, 4, 8, and 16.
pub anisotropy_clamp: u8,
}
impl<L> SamplerDescriptor<L> {
@@ -941,6 +950,7 @@ impl<L> SamplerDescriptor<L> {
lod_min_clamp: self.lod_min_clamp,
lod_max_clamp: self.lod_max_clamp,
compare: self.compare,
anisotropy_clamp: self.anisotropy_clamp,
}
}
}