diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 3967d226da7..f4413d1d3da 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -1322,13 +1322,13 @@ impl Device { }); } - if !(1.0..=16.0).contains(&desc.anisotropy_clamp) { + if desc.anisotropy_clamp < 1 { return Err(resource::CreateSamplerError::InvalidAnisotropy( desc.anisotropy_clamp, )); } - if desc.anisotropy_clamp != 1.0 { + if desc.anisotropy_clamp != 1 { if !matches!(desc.min_filter, wgt::FilterMode::Linear) { return Err( resource::CreateSamplerError::InvalidFilterModeWithAnisotropy { @@ -1358,6 +1358,18 @@ impl Device { } } + let anisotropy_clamp = if self + .downlevel + .flags + .contains(wgt::DownlevelFlags::ANISOTROPIC_FILTERING) + { + // Clamp anisotropy clamp to [1, 16] per the wgpu-hal interface + desc.anisotropy_clamp.min(16) + } else { + // If it isn't supported, set this unconditionally to 1 + 1 + }; + //TODO: check for wgt::DownlevelFlags::COMPARISON_SAMPLERS let hal_desc = hal::SamplerDescriptor { @@ -1368,7 +1380,7 @@ impl Device { mipmap_filter: desc.mipmap_filter, lod_clamp: desc.lod_min_clamp..desc.lod_max_clamp, compare: desc.compare, - anisotropy_clamp: desc.anisotropy_clamp, + anisotropy_clamp, border_color: desc.border_color, }; diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index 5f4fcf83f1f..200be4629e7 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -689,8 +689,8 @@ pub struct SamplerDescriptor<'a> { pub lod_max_clamp: f32, /// If this is enabled, this is a comparison sampler using the given comparison function. pub compare: Option, - /// Valid values between 1 and 16 inclusive. If this is not 1.0, all filter modes must be linear. - pub anisotropy_clamp: f32, + /// Must be at least 1. If this is not 1, all filter modes must be linear. + pub anisotropy_clamp: u16, /// Border color to use when address_mode is /// [`AddressMode::ClampToBorder`](wgt::AddressMode::ClampToBorder) pub border_color: Option, @@ -707,7 +707,7 @@ impl Default for SamplerDescriptor<'_> { lod_min_clamp: 0.0, lod_max_clamp: std::f32::MAX, compare: None, - anisotropy_clamp: 1.0, + anisotropy_clamp: 1, border_color: None, } } @@ -752,13 +752,13 @@ pub enum CreateSamplerError { lod_min_clamp: f32, lod_max_clamp: f32, }, - #[error("Invalid anisotropic clamp: {0}. Must be in the range 1 to 16 inclusive.")] - InvalidAnisotropy(f32), + #[error("Invalid anisotropic clamp: {0}. Must be at least 1.")] + InvalidAnisotropy(u16), #[error("Invalid filter mode for {filter_type:?}: {filter_mode:?}. When anistropic clamp is not 1.0 (it is {anisotropic_clamp}), all filter modes must be linear.")] InvalidFilterModeWithAnisotropy { filter_type: SamplerFilterErrorType, filter_mode: wgt::FilterMode, - anisotropic_clamp: f32, + anisotropic_clamp: u16, }, #[error("Cannot create any more samplers")] TooManyObjects, diff --git a/wgpu-hal/examples/halmark/main.rs b/wgpu-hal/examples/halmark/main.rs index d70908fc6cc..2810d160b10 100644 --- a/wgpu-hal/examples/halmark/main.rs +++ b/wgpu-hal/examples/halmark/main.rs @@ -357,7 +357,7 @@ impl Example { mipmap_filter: wgt::FilterMode::Nearest, lod_clamp: 0.0..32.0, compare: None, - anisotropy_clamp: 1.0, + anisotropy_clamp: 1, border_color: None, }; let sampler = unsafe { device.create_sampler(&sampler_desc).unwrap() }; diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 16b9918f385..7e148185722 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -588,7 +588,7 @@ impl crate::Device for super::Device { | conv::map_filter_mode(desc.mipmap_filter) << d3d12_ty::D3D12_MIP_FILTER_SHIFT | reduction << d3d12_ty::D3D12_FILTER_REDUCTION_TYPE_SHIFT; - if desc.anisotropy_clamp != 1.0 { + if desc.anisotropy_clamp != 1 { filter |= d3d12_ty::D3D12_FILTER_ANISOTROPIC; }; diff --git a/wgpu-hal/src/gles/adapter.rs b/wgpu-hal/src/gles/adapter.rs index 44beb4399c5..46bba478f31 100644 --- a/wgpu-hal/src/gles/adapter.rs +++ b/wgpu-hal/src/gles/adapter.rs @@ -315,10 +315,11 @@ impl super::Adapter { && (vertex_shader_storage_blocks != 0 || vertex_ssbo_false_zero), ); downlevel_flags.set(wgt::DownlevelFlags::FRAGMENT_STORAGE, supports_storage); - downlevel_flags.set( - wgt::DownlevelFlags::ANISOTROPIC_FILTERING, - extensions.contains("EXT_texture_filter_anisotropic"), - ); + if extensions.contains("EXT_texture_filter_anisotropic") { + let max_aniso = + unsafe { gl.get_parameter_i32(glow::MAX_TEXTURE_MAX_ANISOTROPY_EXT) } as u32; + downlevel_flags.set(wgt::DownlevelFlags::ANISOTROPIC_FILTERING, max_aniso >= 16); + } downlevel_flags.set( wgt::DownlevelFlags::BUFFER_BINDINGS_NOT_16_BYTE_ALIGNED, !(cfg!(target_arch = "wasm32") || is_angle), diff --git a/wgpu-hal/src/gles/device.rs b/wgpu-hal/src/gles/device.rs index 208fd0a9bc5..0a1cfaf241b 100644 --- a/wgpu-hal/src/gles/device.rs +++ b/wgpu-hal/src/gles/device.rs @@ -867,9 +867,16 @@ impl crate::Device for super::Device { unsafe { gl.sampler_parameter_f32(raw, glow::TEXTURE_MIN_LOD, desc.lod_clamp.start) }; unsafe { gl.sampler_parameter_f32(raw, glow::TEXTURE_MAX_LOD, desc.lod_clamp.end) }; - unsafe { - gl.sampler_parameter_f32(raw, glow::TEXTURE_MAX_ANISOTROPY, desc.anisotropy_clamp) - }; + // If clamp is not 1, we know anisotropy is supported up to 16x + if desc.anisotropy_clamp != 1 { + unsafe { + gl.sampler_parameter_i32( + raw, + glow::TEXTURE_MAX_ANISOTROPY, + desc.anisotropy_clamp as i32, + ) + }; + } //set_param_float(glow::TEXTURE_LOD_BIAS, info.lod_bias.0); diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index bafa4d8427b..adb5fdc7733 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -921,8 +921,10 @@ pub struct SamplerDescriptor<'a> { pub mipmap_filter: wgt::FilterMode, pub lod_clamp: Range, pub compare: Option, - // Must be in the range 1.0 to 16.0 inclusive. Anisotropic filtering must be supported if this is not 1.0. - pub anisotropy_clamp: f32, + // Must in the range [1, 16]. + // + // Anisotropic filtering must be supported if this is not 1. + pub anisotropy_clamp: u16, pub border_color: Option, } diff --git a/wgpu-hal/src/metal/device.rs b/wgpu-hal/src/metal/device.rs index 48a87757bd4..75c64989d36 100644 --- a/wgpu-hal/src/metal/device.rs +++ b/wgpu-hal/src/metal/device.rs @@ -427,6 +427,7 @@ impl crate::Device for super::Device { descriptor.set_address_mode_t(conv::map_address_mode(t)); descriptor.set_address_mode_r(conv::map_address_mode(r)); + // Anisotropy is always supported on mac up to 16x descriptor.set_max_anisotropy(desc.anisotropy_clamp as _); descriptor.set_lod_min_clamp(desc.lod_clamp.start); diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index 5efeed35e3f..6a281077f7f 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -345,7 +345,10 @@ impl PhysicalDeviceFeatures { caps.supports_extension(vk::KhrSwapchainMutableFormatFn::name()), ); dl_flags.set(Df::CUBE_ARRAY_TEXTURES, self.core.image_cube_array != 0); - dl_flags.set(Df::ANISOTROPIC_FILTERING, self.core.sampler_anisotropy != 0); + dl_flags.set( + Df::ANISOTROPIC_FILTERING, + self.core.sampler_anisotropy >= 16, + ); dl_flags.set( Df::FRAGMENT_WRITABLE_STORAGE, self.core.fragment_stores_and_atomics != 0, @@ -1320,7 +1323,6 @@ impl super::Adapter { }, vendor_id: self.phd_capabilities.properties.vendor_id, timestamp_period: self.phd_capabilities.properties.limits.timestamp_period, - downlevel_flags: self.downlevel_flags, private_caps: self.private_caps.clone(), workarounds: self.workarounds, render_passes: Mutex::new(Default::default()), diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index b476ad7d751..2421572a5ef 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -1120,14 +1120,12 @@ impl crate::Device for super::Device { .compare_op(conv::map_comparison(fun)); } - if self - .shared - .downlevel_flags - .contains(wgt::DownlevelFlags::ANISOTROPIC_FILTERING) - { + if desc.anisotropy_clamp != 1 { + // We only enable the downlevel flag if supports 16x anisotropy, + // and wgpu-hal interface guarentees the clamp is in the range [1, 16] vk_info = vk_info .anisotropy_enable(true) - .max_anisotropy(desc.anisotropy_clamp); + .max_anisotropy(desc.anisotropy_clamp as f32); } if let Some(color) = desc.border_color { diff --git a/wgpu-hal/src/vulkan/mod.rs b/wgpu-hal/src/vulkan/mod.rs index af322e0ee86..fdee547973a 100644 --- a/wgpu-hal/src/vulkan/mod.rs +++ b/wgpu-hal/src/vulkan/mod.rs @@ -249,7 +249,6 @@ struct DeviceShared { extension_fns: DeviceExtensionFunctions, vendor_id: u32, timestamp_period: f32, - downlevel_flags: wgt::DownlevelFlags, private_caps: PrivateCapabilities, workarounds: Workarounds, render_passes: Mutex>, diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 8d4efbe5614..ee92091f011 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -1008,8 +1008,8 @@ pub struct SamplerDescriptor<'a> { pub lod_max_clamp: f32, /// If this is enabled, this is a comparison sampler using the given comparison function. pub compare: Option, - /// Valid values between 1 and 16 inclusive. If this is not 1.0, all filter modes must be linear. - pub anisotropy_clamp: f32, + /// Must be at least 1. If this is not 1, all filter modes must be linear. + pub anisotropy_clamp: u16, /// Border color to use when address_mode is [`AddressMode::ClampToBorder`] pub border_color: Option, } @@ -1026,9 +1026,9 @@ impl Default for SamplerDescriptor<'_> { min_filter: Default::default(), mipmap_filter: Default::default(), lod_min_clamp: 0.0, - lod_max_clamp: std::f32::MAX, + lod_max_clamp: 32.0, compare: None, - anisotropy_clamp: 1.0, + anisotropy_clamp: 1, border_color: None, } }