mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 06:44:14 +00:00
Add feature float32-filterable (#4759)
This commit is contained in:
parent
dd7e33250b
commit
32c5a22293
@ -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).
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//! Tests for texture copy bounds checks.
|
//! Tests for BGRA8UNORM_STORAGE feature
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
75
tests/tests/float32_filterable.rs
Normal file
75
tests/tests/float32_filterable.rs
Normal 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);
|
||||||
|
});
|
@ -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;
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
//
|
//
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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],
|
||||||
|
@ -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
|
||||||
|
@ -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`
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user