Add feature float32-filterable (#4759)

This commit is contained in:
Almar Klein 2023-12-04 14:23:13 +01:00 committed by GitHub
parent dd7e33250b
commit 32c5a22293
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 191 additions and 30 deletions

View File

@ -53,6 +53,7 @@ Previously, `DeviceExt::create_texture_with_data` only allowed data to be provid
#### General #### General
- Added `DownlevelFlags::VERTEX_AND_INSTANCE_INDEX_RESPECTS_RESPECTIVE_FIRST_VALUE_IN_INDIRECT_DRAW` to know if `@builtin(vertex_index)` and `@builtin(instance_index)` will respect the `first_vertex` / `first_instance` in indirect calls. If this is not present, both will always start counting from 0. Currently enabled on all backends except DX12. By @cwfitzgerald in [#4722](https://github.com/gfx-rs/wgpu/pull/4722) - Added `DownlevelFlags::VERTEX_AND_INSTANCE_INDEX_RESPECTS_RESPECTIVE_FIRST_VALUE_IN_INDIRECT_DRAW` to know if `@builtin(vertex_index)` and `@builtin(instance_index)` will respect the `first_vertex` / `first_instance` in indirect calls. If this is not present, both will always start counting from 0. Currently enabled on all backends except DX12. By @cwfitzgerald in [#4722](https://github.com/gfx-rs/wgpu/pull/4722)
- No longer validate surfaces against their allowed extent range on configure. This caused warnings that were almost impossible to avoid. As before, the resulting behavior depends on the compositor. By @wumpf in [#????](https://github.com/gfx-rs/wgpu/pull/????) - No longer validate surfaces against their allowed extent range on configure. This caused warnings that were almost impossible to avoid. As before, the resulting behavior depends on the compositor. By @wumpf in [#????](https://github.com/gfx-rs/wgpu/pull/????)
- Added support for the float32-filterable feature. By @almarklein in [#4759](https://github.com/gfx-rs/wgpu/pull/4759)
#### OpenGL #### OpenGL
- `@builtin(instance_index)` now properly reflects the range provided in the draw call instead of always counting from 0. By @cwfitzgerald in [#4722](https://github.com/gfx-rs/wgpu/pull/4722). - `@builtin(instance_index)` now properly reflects the range provided in the draw call instead of always counting from 0. By @cwfitzgerald in [#4722](https://github.com/gfx-rs/wgpu/pull/4722).

View File

@ -4980,6 +4980,7 @@ webidl.converters["GPUFeatureName"] = webidl.createEnumConverter(
"texture-compression-astc", "texture-compression-astc",
"rg11b10ufloat-renderable", "rg11b10ufloat-renderable",
"bgra8unorm-storage", "bgra8unorm-storage",
"float32-filterable",
// extended from spec // extended from spec

View File

@ -266,6 +266,9 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
if features.contains(wgpu_types::Features::BGRA8UNORM_STORAGE) { if features.contains(wgpu_types::Features::BGRA8UNORM_STORAGE) {
return_features.push("bgra8unorm-storage"); return_features.push("bgra8unorm-storage");
} }
if features.contains(wgpu_types::Features::FLOAT32_FILTERABLE) {
return_features.push("float32-filterable");
}
// extended from spec // extended from spec
@ -498,6 +501,10 @@ impl From<GpuRequiredFeatures> for wgpu_types::Features {
wgpu_types::Features::BGRA8UNORM_STORAGE, wgpu_types::Features::BGRA8UNORM_STORAGE,
required_features.0.contains("bgra8unorm-storage"), required_features.0.contains("bgra8unorm-storage"),
); );
features.set(
wgpu_types::Features::FLOAT32_FILTERABLE,
required_features.0.contains("float32-filterable"),
);
// extended from spec // extended from spec

View File

@ -103,6 +103,7 @@ enum GPUFeatureName {
"shader-f16", "shader-f16",
"rg11b10ufloat-renderable", "rg11b10ufloat-renderable",
"bgra8unorm-storage", "bgra8unorm-storage",
"float32-filterable",
// extended from spec // extended from spec

View File

@ -1,4 +1,4 @@
//! Tests for texture copy bounds checks. //! Tests for BGRA8UNORM_STORAGE feature
use std::borrow::Cow; use std::borrow::Cow;

View File

@ -0,0 +1,75 @@
//! Tests for FLOAT32_FILTERABLE feature.
use wgpu_test::{fail, gpu_test, GpuTestConfiguration, TestParameters};
fn create_texture_binding(device: &wgpu::Device, format: wgpu::TextureFormat, filterable: bool) {
let texture = device.create_texture(&wgpu::TextureDescriptor {
label: None,
size: wgpu::Extent3d {
width: 256,
height: 256,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
view_formats: &[],
});
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
let bgl = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None,
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
sample_type: wgpu::TextureSampleType::Float { filterable },
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
},
count: None,
}],
});
let _bg = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &bgl,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(&view),
}],
});
}
#[gpu_test]
static FLOAT32_FILTERABLE_WITHOUT_FEATURE: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(TestParameters::default())
.run_sync(|ctx| {
let device = &ctx.device;
// Unorm textures are always filterable
create_texture_binding(device, wgpu::TextureFormat::R8Unorm, true);
create_texture_binding(device, wgpu::TextureFormat::R8Unorm, false);
// As are float16 textures
create_texture_binding(device, wgpu::TextureFormat::R16Float, true);
create_texture_binding(device, wgpu::TextureFormat::R16Float, false);
// Float 32 textures can be used as non-filterable only
create_texture_binding(device, wgpu::TextureFormat::R32Float, false);
// This is supposed to fail, since we have not activated the feature
fail(&ctx.device, || {
create_texture_binding(device, wgpu::TextureFormat::R32Float, true);
});
});
#[gpu_test]
static FLOAT32_FILTERABLE_WITH_FEATURE: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(TestParameters::default().features(wgpu::Features::FLOAT32_FILTERABLE))
.run_sync(|ctx| {
let device = &ctx.device;
// With the feature enabled, it does work!
create_texture_binding(device, wgpu::TextureFormat::R32Float, true);
create_texture_binding(device, wgpu::TextureFormat::Rg32Float, true);
create_texture_binding(device, wgpu::TextureFormat::Rgba32Float, true);
});

View File

@ -15,6 +15,7 @@ mod create_surface_error;
mod device; mod device;
mod encoder; mod encoder;
mod external_texture; mod external_texture;
mod float32_filterable;
mod instance; mod instance;
mod life_cycle; mod life_cycle;
mod mem_leaks; mod mem_leaks;

View File

@ -2064,7 +2064,7 @@ impl<A: HalApi> Device<A> {
.views .views
.add_single(&*texture_view_guard, id) .add_single(&*texture_view_guard, id)
.ok_or(Error::InvalidTextureView(id))?; .ok_or(Error::InvalidTextureView(id))?;
let (pub_usage, internal_use) = Self::texture_use_parameters( let (pub_usage, internal_use) = self.texture_use_parameters(
binding, binding,
decl, decl,
view, view,
@ -2095,7 +2095,7 @@ impl<A: HalApi> Device<A> {
.add_single(&*texture_view_guard, id) .add_single(&*texture_view_guard, id)
.ok_or(Error::InvalidTextureView(id))?; .ok_or(Error::InvalidTextureView(id))?;
let (pub_usage, internal_use) = let (pub_usage, internal_use) =
Self::texture_use_parameters(binding, decl, view, self.texture_use_parameters(binding, decl, view,
"SampledTextureArray, ReadonlyStorageTextureArray or WriteonlyStorageTextureArray")?; "SampledTextureArray, ReadonlyStorageTextureArray or WriteonlyStorageTextureArray")?;
Self::create_texture_binding( Self::create_texture_binding(
view, view,
@ -2197,6 +2197,7 @@ impl<A: HalApi> Device<A> {
} }
pub(crate) fn texture_use_parameters( pub(crate) fn texture_use_parameters(
self: &Arc<Self>,
binding: u32, binding: u32,
decl: &wgt::BindGroupLayoutEntry, decl: &wgt::BindGroupLayoutEntry,
view: &TextureView<A>, view: &TextureView<A>,
@ -2227,7 +2228,7 @@ impl<A: HalApi> Device<A> {
let compat_sample_type = view let compat_sample_type = view
.desc .desc
.format .format
.sample_type(Some(view.desc.range.aspect)) .sample_type(Some(view.desc.range.aspect), Some(self.features))
.unwrap(); .unwrap();
match (sample_type, compat_sample_type) { match (sample_type, compat_sample_type) {
(Tst::Uint, Tst::Uint) | (Tst::Uint, Tst::Uint) |
@ -3198,6 +3199,24 @@ impl<A: HalApi> Device<A> {
Ok(pipeline) Ok(pipeline)
} }
pub(crate) fn get_texture_format_features(
&self,
adapter: &Adapter<A>,
format: TextureFormat,
) -> wgt::TextureFormatFeatures {
// Variant of adapter.get_texture_format_features that takes device features into account
use wgt::TextureFormatFeatureFlags as tfsc;
let mut format_features = adapter.get_texture_format_features(format);
if (format == TextureFormat::R32Float
|| format == TextureFormat::Rg32Float
|| format == TextureFormat::Rgba32Float)
&& !self.features.contains(wgt::Features::FLOAT32_FILTERABLE)
{
format_features.flags.set(tfsc::FILTERABLE, false);
}
format_features
}
pub(crate) fn describe_format_features( pub(crate) fn describe_format_features(
&self, &self,
adapter: &Adapter<A>, adapter: &Adapter<A>,
@ -3213,7 +3232,7 @@ impl<A: HalApi> Device<A> {
let downlevel = !self.downlevel.is_webgpu_compliant(); let downlevel = !self.downlevel.is_webgpu_compliant();
if using_device_features || downlevel { if using_device_features || downlevel {
Ok(adapter.get_texture_format_features(format)) Ok(self.get_texture_format_features(adapter, format))
} else { } else {
Ok(format.guaranteed_format_features(self.features)) Ok(format.guaranteed_format_features(self.features))
} }

View File

@ -155,6 +155,10 @@ impl super::Adapter {
// bgra8unorm-storage is never supported on dx11 according to: // bgra8unorm-storage is never supported on dx11 according to:
// https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/format-support-for-direct3d-11-0-feature-level-hardware#dxgi_format_b8g8r8a8_unormfcs-87 // https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/format-support-for-direct3d-11-0-feature-level-hardware#dxgi_format_b8g8r8a8_unormfcs-87
// float32-filterable should always be available on dx11
// https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/format-support-for-direct3d-11-0-feature-level-hardware#dxgi_format_r32g32b32a32_floatfcs-2
features.set(wgt::Features::FLOAT32_FILTERABLE, true);
// //
// Fill out limits and alignments // Fill out limits and alignments
// //

View File

@ -294,6 +294,9 @@ impl super::Adapter {
bgra8unorm_storage_supported, bgra8unorm_storage_supported,
); );
// float32-filterable should always be available on d3d12
features.set(wgt::Features::FLOAT32_FILTERABLE, true);
// TODO: Determine if IPresentationManager is supported // TODO: Determine if IPresentationManager is supported
let presentation_timer = auxil::dxgi::time::PresentationTimer::new_dxgi(); let presentation_timer = auxil::dxgi::time::PresentationTimer::new_dxgi();

View File

@ -549,6 +549,13 @@ impl super::Adapter {
); );
} }
features.set(
wgt::Features::FLOAT32_FILTERABLE,
extensions.contains("GL_ARB_color_buffer_float")
|| extensions.contains("GL_EXT_color_buffer_float")
|| extensions.contains("OES_texture_float_linear"),
);
// We *might* be able to emulate bgra8unorm-storage but currently don't attempt to. // We *might* be able to emulate bgra8unorm-storage but currently don't attempt to.
let mut private_caps = super::PrivateCapabilities::empty(); let mut private_caps = super::PrivateCapabilities::empty();
@ -594,14 +601,6 @@ impl super::Adapter {
super::PrivateCapabilities::COLOR_BUFFER_FLOAT, super::PrivateCapabilities::COLOR_BUFFER_FLOAT,
color_buffer_float, color_buffer_float,
); );
private_caps.set(
super::PrivateCapabilities::TEXTURE_FLOAT_LINEAR,
if full_ver.is_some() {
color_buffer_float
} else {
extensions.contains("OES_texture_float_linear")
},
);
private_caps.set(super::PrivateCapabilities::QUERY_BUFFERS, query_buffers); private_caps.set(super::PrivateCapabilities::QUERY_BUFFERS, query_buffers);
private_caps.set(super::PrivateCapabilities::QUERY_64BIT, full_ver.is_some()); private_caps.set(super::PrivateCapabilities::QUERY_64BIT, full_ver.is_some());
private_caps.set( private_caps.set(
@ -1022,8 +1021,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
| Tfc::MULTISAMPLE_RESOLVE, | Tfc::MULTISAMPLE_RESOLVE,
); );
let texture_float_linear = let texture_float_linear = feature_fn(wgt::Features::FLOAT32_FILTERABLE, filterable);
private_caps_fn(super::PrivateCapabilities::TEXTURE_FLOAT_LINEAR, filterable);
match format { match format {
Tf::R8Unorm => filterable_renderable, Tf::R8Unorm => filterable_renderable,

View File

@ -605,7 +605,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
if !cat.ops.contains(crate::AttachmentOps::LOAD) { if !cat.ops.contains(crate::AttachmentOps::LOAD) {
let c = &cat.clear_value; let c = &cat.clear_value;
self.cmd_buffer.commands.push( self.cmd_buffer.commands.push(
match cat.target.view.format.sample_type(None).unwrap() { match cat.target.view.format.sample_type(None, None).unwrap() {
wgt::TextureSampleType::Float { .. } => C::ClearColorF { wgt::TextureSampleType::Float { .. } => C::ClearColorF {
draw_buffer: i as u32, draw_buffer: i as u32,
color: [c.r as f32, c.g as f32, c.b as f32, c.a as f32], color: [c.r as f32, c.g as f32, c.b as f32, c.a as f32],

View File

@ -746,7 +746,7 @@ impl crate::Device<super::Api> for super::Device {
unsafe { gl.bind_texture(target, Some(raw)) }; unsafe { gl.bind_texture(target, Some(raw)) };
//Note: this has to be done before defining the storage! //Note: this has to be done before defining the storage!
match desc.format.sample_type(None) { match desc.format.sample_type(None, Some(self.shared.features)) {
Some( Some(
wgt::TextureSampleType::Float { filterable: false } wgt::TextureSampleType::Float { filterable: false }
| wgt::TextureSampleType::Uint | wgt::TextureSampleType::Uint

View File

@ -186,8 +186,6 @@ bitflags::bitflags! {
const COLOR_BUFFER_HALF_FLOAT = 1 << 8; const COLOR_BUFFER_HALF_FLOAT = 1 << 8;
/// Supports `f11/f10` and `f32` color buffers /// Supports `f11/f10` and `f32` color buffers
const COLOR_BUFFER_FLOAT = 1 << 9; const COLOR_BUFFER_FLOAT = 1 << 9;
/// Supports linear flitering `f32` textures.
const TEXTURE_FLOAT_LINEAR = 1 << 10;
/// Supports query buffer objects. /// Supports query buffer objects.
const QUERY_BUFFERS = 1 << 11; const QUERY_BUFFERS = 1 << 11;
/// Supports 64 bit queries via `glGetQueryObjectui64v` /// Supports 64 bit queries via `glGetQueryObjectui64v`

View File

@ -604,6 +604,9 @@ impl super::PrivateCapabilities {
function_specialization: Self::supports_any(device, FUNCTION_SPECIALIZATION_SUPPORT), function_specialization: Self::supports_any(device, FUNCTION_SPECIALIZATION_SUPPORT),
depth_clip_mode: Self::supports_any(device, DEPTH_CLIP_MODE), depth_clip_mode: Self::supports_any(device, DEPTH_CLIP_MODE),
texture_cube_array: Self::supports_any(device, TEXTURE_CUBE_ARRAY_SUPPORT), texture_cube_array: Self::supports_any(device, TEXTURE_CUBE_ARRAY_SUPPORT),
supports_float_filtering: os_is_mac
|| (version.at_least((11, 0), (14, 0), os_is_mac)
&& device.supports_32bit_float_filtering()),
format_depth24_stencil8: os_is_mac && device.d24_s8_supported(), format_depth24_stencil8: os_is_mac && device.d24_s8_supported(),
format_depth32_stencil8_filter: os_is_mac, format_depth32_stencil8_filter: os_is_mac,
format_depth32_stencil8_none: !os_is_mac, format_depth32_stencil8_none: !os_is_mac,
@ -821,6 +824,7 @@ impl super::PrivateCapabilities {
| F::DEPTH32FLOAT_STENCIL8 | F::DEPTH32FLOAT_STENCIL8
| F::BGRA8UNORM_STORAGE; | F::BGRA8UNORM_STORAGE;
features.set(F::FLOAT32_FILTERABLE, self.supports_float_filtering);
features.set( features.set(
F::INDIRECT_FIRST_INSTANCE | F::MULTI_DRAW_INDIRECT, F::INDIRECT_FIRST_INSTANCE | F::MULTI_DRAW_INDIRECT,
self.indirect_draw_dispatch, self.indirect_draw_dispatch,

View File

@ -191,6 +191,7 @@ struct PrivateCapabilities {
function_specialization: bool, function_specialization: bool,
depth_clip_mode: bool, depth_clip_mode: bool,
texture_cube_array: bool, texture_cube_array: bool,
supports_float_filtering: bool,
format_depth24_stencil8: bool, format_depth24_stencil8: bool,
format_depth32_stencil8_filter: bool, format_depth32_stencil8_filter: bool,
format_depth32_stencil8_none: bool, format_depth32_stencil8_none: bool,

View File

@ -536,6 +536,10 @@ impl PhysicalDeviceFeatures {
supports_bgra8unorm_storage(instance, phd, caps.device_api_version), supports_bgra8unorm_storage(instance, phd, caps.device_api_version),
); );
features.set(
F::FLOAT32_FILTERABLE,
is_float32_filterable_supported(instance, phd),
);
features.set( features.set(
F::TEXTURE_FORMAT_NV12, F::TEXTURE_FORMAT_NV12,
(caps.device_api_version >= vk::API_VERSION_1_1 (caps.device_api_version >= vk::API_VERSION_1_1
@ -1568,8 +1572,8 @@ impl crate::Adapter<super::Api> for super::Adapter {
.framebuffer_stencil_sample_counts .framebuffer_stencil_sample_counts
.min(limits.sampled_image_stencil_sample_counts) .min(limits.sampled_image_stencil_sample_counts)
} else { } else {
match format.sample_type(None) { match format.sample_type(None, None) {
Some(wgt::TextureSampleType::Float { filterable: _ }) => limits Some(wgt::TextureSampleType::Float { .. }) => limits
.framebuffer_color_sample_counts .framebuffer_color_sample_counts
.min(limits.sampled_image_color_sample_counts), .min(limits.sampled_image_color_sample_counts),
Some(wgt::TextureSampleType::Sint) | Some(wgt::TextureSampleType::Uint) => { Some(wgt::TextureSampleType::Sint) | Some(wgt::TextureSampleType::Uint) => {
@ -1760,6 +1764,21 @@ fn is_format_16bit_norm_supported(instance: &ash::Instance, phd: vk::PhysicalDev
r16unorm && r16snorm && rg16unorm && rg16snorm && rgba16unorm && rgba16snorm r16unorm && r16snorm && rg16unorm && rg16snorm && rgba16unorm && rgba16snorm
} }
fn is_float32_filterable_supported(instance: &ash::Instance, phd: vk::PhysicalDevice) -> bool {
let tiling = vk::ImageTiling::OPTIMAL;
let features = vk::FormatFeatureFlags::SAMPLED_IMAGE_FILTER_LINEAR;
let r_float = supports_format(instance, phd, vk::Format::R32_SFLOAT, tiling, features);
let rg_float = supports_format(instance, phd, vk::Format::R32G32_SFLOAT, tiling, features);
let rgba_float = supports_format(
instance,
phd,
vk::Format::R32G32B32A32_SFLOAT,
tiling,
features,
);
r_float && rg_float && rgba_float
}
fn supports_format( fn supports_format(
instance: &ash::Instance, instance: &ash::Instance,
phd: vk::PhysicalDevice, phd: vk::PhysicalDevice,

View File

@ -200,7 +200,7 @@ impl crate::ColorAttachment<'_, super::Api> {
.view .view
.attachment .attachment
.view_format .view_format
.sample_type(None) .sample_type(None, None)
.unwrap() .unwrap()
{ {
wgt::TextureSampleType::Float { .. } => vk::ClearColorValue { wgt::TextureSampleType::Float { .. } => vk::ClearColorValue {

View File

@ -337,7 +337,18 @@ bitflags::bitflags! {
// ? const NORM16_FILTERABLE = 1 << 17; (https://github.com/gpuweb/gpuweb/issues/3839) // ? const NORM16_FILTERABLE = 1 << 17; (https://github.com/gpuweb/gpuweb/issues/3839)
// ? const NORM16_RESOLVE = 1 << 18; (https://github.com/gpuweb/gpuweb/issues/3839) // ? const NORM16_RESOLVE = 1 << 18; (https://github.com/gpuweb/gpuweb/issues/3839)
// TODO const FLOAT32_FILTERABLE = 1 << 19;
/// Allows textures with formats "r32float", "rg32float", and "rgba32float" to be filterable.
///
/// Supported Platforms:
/// - Vulkan (mainly on Desktop GPUs)
/// - DX12
/// - Metal on macOS or Apple9+ GPUs, optional on iOS/iPadOS with Apple7/8 GPUs
/// - GL with one of `GL_ARB_color_buffer_float`/`GL_EXT_color_buffer_float`/`OES_texture_float_linear`
///
/// This is a web and native feature.
const FLOAT32_FILTERABLE = 1 << 19;
// ? const FLOAT32_BLENDABLE = 1 << 20; (https://github.com/gpuweb/gpuweb/issues/3556) // ? const FLOAT32_BLENDABLE = 1 << 20; (https://github.com/gpuweb/gpuweb/issues/3556)
// ? const 32BIT_FORMAT_MULTISAMPLE = 1 << 21; (https://github.com/gpuweb/gpuweb/issues/3844) // ? const 32BIT_FORMAT_MULTISAMPLE = 1 << 21; (https://github.com/gpuweb/gpuweb/issues/3844)
// ? const 32BIT_FORMAT_RESOLVE = 1 << 22; (https://github.com/gpuweb/gpuweb/issues/3844) // ? const 32BIT_FORMAT_RESOLVE = 1 << 22; (https://github.com/gpuweb/gpuweb/issues/3844)
@ -3218,10 +3229,16 @@ impl TextureFormat {
Self::Astc { .. } => ( noaa, basic), Self::Astc { .. } => ( noaa, basic),
}; };
let is_filterable = // Get whether the format is filterable, taking features into account
self.sample_type(None) == Some(TextureSampleType::Float { filterable: true }); let sample_type1 = self.sample_type(None, Some(device_features));
let is_filterable = sample_type1 == Some(TextureSampleType::Float { filterable: true });
// Features that enable filtering don't affect blendability
let sample_type2 = self.sample_type(None, None);
let is_blendable = sample_type2 == Some(TextureSampleType::Float { filterable: true });
flags.set(TextureFormatFeatureFlags::FILTERABLE, is_filterable); flags.set(TextureFormatFeatureFlags::FILTERABLE, is_filterable);
flags.set(TextureFormatFeatureFlags::BLENDABLE, is_filterable); flags.set(TextureFormatFeatureFlags::BLENDABLE, is_blendable);
TextureFormatFeatures { TextureFormatFeatures {
allowed_usages, allowed_usages,
@ -3233,9 +3250,17 @@ impl TextureFormat {
/// ///
/// Returns `None` only if the format is combined depth-stencil /// Returns `None` only if the format is combined depth-stencil
/// and `TextureAspect::All` or no `aspect` was provided /// and `TextureAspect::All` or no `aspect` was provided
pub fn sample_type(&self, aspect: Option<TextureAspect>) -> Option<TextureSampleType> { pub fn sample_type(
&self,
aspect: Option<TextureAspect>,
device_features: Option<Features>,
) -> Option<TextureSampleType> {
let float = TextureSampleType::Float { filterable: true }; let float = TextureSampleType::Float { filterable: true };
let unfilterable_float = TextureSampleType::Float { filterable: false }; let float32_sample_type = TextureSampleType::Float {
filterable: device_features
.unwrap_or(Features::empty())
.contains(Features::FLOAT32_FILTERABLE),
};
let depth = TextureSampleType::Depth; let depth = TextureSampleType::Depth;
let uint = TextureSampleType::Uint; let uint = TextureSampleType::Uint;
let sint = TextureSampleType::Sint; let sint = TextureSampleType::Sint;
@ -3256,7 +3281,7 @@ impl TextureFormat {
| Self::Rgb10a2Unorm | Self::Rgb10a2Unorm
| Self::Rg11b10Float => Some(float), | Self::Rg11b10Float => Some(float),
Self::R32Float | Self::Rg32Float | Self::Rgba32Float => Some(unfilterable_float), Self::R32Float | Self::Rg32Float | Self::Rgba32Float => Some(float32_sample_type),
Self::R8Uint Self::R8Uint
| Self::Rg8Uint | Self::Rg8Uint

View File

@ -661,7 +661,7 @@ fn map_map_mode(mode: crate::MapMode) -> u32 {
} }
} }
const FEATURES_MAPPING: [(wgt::Features, web_sys::GpuFeatureName); 10] = [ const FEATURES_MAPPING: [(wgt::Features, web_sys::GpuFeatureName); 11] = [
//TODO: update the name //TODO: update the name
( (
wgt::Features::DEPTH_CLIP_CONTROL, wgt::Features::DEPTH_CLIP_CONTROL,
@ -703,6 +703,10 @@ const FEATURES_MAPPING: [(wgt::Features, web_sys::GpuFeatureName); 10] = [
wgt::Features::BGRA8UNORM_STORAGE, wgt::Features::BGRA8UNORM_STORAGE,
web_sys::GpuFeatureName::Bgra8unormStorage, web_sys::GpuFeatureName::Bgra8unormStorage,
), ),
(
wgt::Features::FLOAT32_FILTERABLE,
web_sys::GpuFeatureName::Float32Filterable,
),
]; ];
fn map_wgt_features(supported_features: web_sys::GpuSupportedFeatures) -> wgt::Features { fn map_wgt_features(supported_features: web_sys::GpuSupportedFeatures) -> wgt::Features {