Skip to content

Commit

Permalink
Add feature float32-filterable (#4759)
Browse files Browse the repository at this point in the history
  • Loading branch information
almarklein authored Dec 4, 2023
1 parent dd7e332 commit 32c5a22
Show file tree
Hide file tree
Showing 20 changed files with 191 additions and 30 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Previously, `DeviceExt::create_texture_with_data` only allowed data to be provid
#### 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)
- 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
- `@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).
Expand Down
1 change: 1 addition & 0 deletions deno_webgpu/01_webgpu.js
Original file line number Diff line number Diff line change
Expand Up @@ -4980,6 +4980,7 @@ webidl.converters["GPUFeatureName"] = webidl.createEnumConverter(
"texture-compression-astc",
"rg11b10ufloat-renderable",
"bgra8unorm-storage",
"float32-filterable",

// extended from spec

Expand Down
7 changes: 7 additions & 0 deletions deno_webgpu/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,9 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
if features.contains(wgpu_types::Features::BGRA8UNORM_STORAGE) {
return_features.push("bgra8unorm-storage");
}
if features.contains(wgpu_types::Features::FLOAT32_FILTERABLE) {
return_features.push("float32-filterable");
}

// extended from spec

Expand Down Expand Up @@ -498,6 +501,10 @@ impl From<GpuRequiredFeatures> for wgpu_types::Features {
wgpu_types::Features::BGRA8UNORM_STORAGE,
required_features.0.contains("bgra8unorm-storage"),
);
features.set(
wgpu_types::Features::FLOAT32_FILTERABLE,
required_features.0.contains("float32-filterable"),
);

// extended from spec

Expand Down
1 change: 1 addition & 0 deletions deno_webgpu/webgpu.idl
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ enum GPUFeatureName {
"shader-f16",
"rg11b10ufloat-renderable",
"bgra8unorm-storage",
"float32-filterable",

// extended from spec

Expand Down
2 changes: 1 addition & 1 deletion tests/tests/bgra8unorm_storage.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Tests for texture copy bounds checks.
//! Tests for BGRA8UNORM_STORAGE feature
use std::borrow::Cow;

Expand Down
75 changes: 75 additions & 0 deletions tests/tests/float32_filterable.rs
Original file line number Diff line number Diff line change
@@ -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);
});
1 change: 1 addition & 0 deletions tests/tests/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod create_surface_error;
mod device;
mod encoder;
mod external_texture;
mod float32_filterable;
mod instance;
mod life_cycle;
mod mem_leaks;
Expand Down
27 changes: 23 additions & 4 deletions wgpu-core/src/device/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2064,7 +2064,7 @@ impl<A: HalApi> Device<A> {
.views
.add_single(&*texture_view_guard, 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,
decl,
view,
Expand Down Expand Up @@ -2095,7 +2095,7 @@ impl<A: HalApi> Device<A> {
.add_single(&*texture_view_guard, id)
.ok_or(Error::InvalidTextureView(id))?;
let (pub_usage, internal_use) =
Self::texture_use_parameters(binding, decl, view,
self.texture_use_parameters(binding, decl, view,
"SampledTextureArray, ReadonlyStorageTextureArray or WriteonlyStorageTextureArray")?;
Self::create_texture_binding(
view,
Expand Down Expand Up @@ -2197,6 +2197,7 @@ impl<A: HalApi> Device<A> {
}

pub(crate) fn texture_use_parameters(
self: &Arc<Self>,
binding: u32,
decl: &wgt::BindGroupLayoutEntry,
view: &TextureView<A>,
Expand Down Expand Up @@ -2227,7 +2228,7 @@ impl<A: HalApi> Device<A> {
let compat_sample_type = view
.desc
.format
.sample_type(Some(view.desc.range.aspect))
.sample_type(Some(view.desc.range.aspect), Some(self.features))
.unwrap();
match (sample_type, compat_sample_type) {
(Tst::Uint, Tst::Uint) |
Expand Down Expand Up @@ -3198,6 +3199,24 @@ impl<A: HalApi> Device<A> {
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(
&self,
adapter: &Adapter<A>,
Expand All @@ -3213,7 +3232,7 @@ impl<A: HalApi> Device<A> {
let downlevel = !self.downlevel.is_webgpu_compliant();

if using_device_features || downlevel {
Ok(adapter.get_texture_format_features(format))
Ok(self.get_texture_format_features(adapter, format))
} else {
Ok(format.guaranteed_format_features(self.features))
}
Expand Down
4 changes: 4 additions & 0 deletions wgpu-hal/src/dx11/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ impl super::Adapter {
// 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

// 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
//
Expand Down
3 changes: 3 additions & 0 deletions wgpu-hal/src/dx12/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ impl super::Adapter {
bgra8unorm_storage_supported,
);

// float32-filterable should always be available on d3d12
features.set(wgt::Features::FLOAT32_FILTERABLE, true);

// TODO: Determine if IPresentationManager is supported
let presentation_timer = auxil::dxgi::time::PresentationTimer::new_dxgi();

Expand Down
18 changes: 8 additions & 10 deletions wgpu-hal/src/gles/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.

let mut private_caps = super::PrivateCapabilities::empty();
Expand Down Expand Up @@ -594,14 +601,6 @@ impl super::Adapter {
super::PrivateCapabilities::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_64BIT, full_ver.is_some());
private_caps.set(
Expand Down Expand Up @@ -1022,8 +1021,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
| Tfc::MULTISAMPLE_RESOLVE,
);

let texture_float_linear =
private_caps_fn(super::PrivateCapabilities::TEXTURE_FLOAT_LINEAR, filterable);
let texture_float_linear = feature_fn(wgt::Features::FLOAT32_FILTERABLE, filterable);

match format {
Tf::R8Unorm => filterable_renderable,
Expand Down
2 changes: 1 addition & 1 deletion wgpu-hal/src/gles/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
if !cat.ops.contains(crate::AttachmentOps::LOAD) {
let c = &cat.clear_value;
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 {
draw_buffer: i as u32,
color: [c.r as f32, c.g as f32, c.b as f32, c.a as f32],
Expand Down
2 changes: 1 addition & 1 deletion wgpu-hal/src/gles/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ impl crate::Device<super::Api> for super::Device {

unsafe { gl.bind_texture(target, Some(raw)) };
//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(
wgt::TextureSampleType::Float { filterable: false }
| wgt::TextureSampleType::Uint
Expand Down
2 changes: 0 additions & 2 deletions wgpu-hal/src/gles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,6 @@ bitflags::bitflags! {
const COLOR_BUFFER_HALF_FLOAT = 1 << 8;
/// Supports `f11/f10` and `f32` color buffers
const COLOR_BUFFER_FLOAT = 1 << 9;
/// Supports linear flitering `f32` textures.
const TEXTURE_FLOAT_LINEAR = 1 << 10;
/// Supports query buffer objects.
const QUERY_BUFFERS = 1 << 11;
/// Supports 64 bit queries via `glGetQueryObjectui64v`
Expand Down
4 changes: 4 additions & 0 deletions wgpu-hal/src/metal/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,9 @@ impl super::PrivateCapabilities {
function_specialization: Self::supports_any(device, FUNCTION_SPECIALIZATION_SUPPORT),
depth_clip_mode: Self::supports_any(device, DEPTH_CLIP_MODE),
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_depth32_stencil8_filter: os_is_mac,
format_depth32_stencil8_none: !os_is_mac,
Expand Down Expand Up @@ -821,6 +824,7 @@ impl super::PrivateCapabilities {
| F::DEPTH32FLOAT_STENCIL8
| F::BGRA8UNORM_STORAGE;

features.set(F::FLOAT32_FILTERABLE, self.supports_float_filtering);
features.set(
F::INDIRECT_FIRST_INSTANCE | F::MULTI_DRAW_INDIRECT,
self.indirect_draw_dispatch,
Expand Down
1 change: 1 addition & 0 deletions wgpu-hal/src/metal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ struct PrivateCapabilities {
function_specialization: bool,
depth_clip_mode: bool,
texture_cube_array: bool,
supports_float_filtering: bool,
format_depth24_stencil8: bool,
format_depth32_stencil8_filter: bool,
format_depth32_stencil8_none: bool,
Expand Down
23 changes: 21 additions & 2 deletions wgpu-hal/src/vulkan/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,10 @@ impl PhysicalDeviceFeatures {
supports_bgra8unorm_storage(instance, phd, caps.device_api_version),
);

features.set(
F::FLOAT32_FILTERABLE,
is_float32_filterable_supported(instance, phd),
);
features.set(
F::TEXTURE_FORMAT_NV12,
(caps.device_api_version >= vk::API_VERSION_1_1
Expand Down Expand Up @@ -1568,8 +1572,8 @@ impl crate::Adapter<super::Api> for super::Adapter {
.framebuffer_stencil_sample_counts
.min(limits.sampled_image_stencil_sample_counts)
} else {
match format.sample_type(None) {
Some(wgt::TextureSampleType::Float { filterable: _ }) => limits
match format.sample_type(None, None) {
Some(wgt::TextureSampleType::Float { .. }) => limits
.framebuffer_color_sample_counts
.min(limits.sampled_image_color_sample_counts),
Some(wgt::TextureSampleType::Sint) | Some(wgt::TextureSampleType::Uint) => {
Expand Down Expand Up @@ -1760,6 +1764,21 @@ fn is_format_16bit_norm_supported(instance: &ash::Instance, phd: vk::PhysicalDev
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(
instance: &ash::Instance,
phd: vk::PhysicalDevice,
Expand Down
2 changes: 1 addition & 1 deletion wgpu-hal/src/vulkan/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ impl crate::ColorAttachment<'_, super::Api> {
.view
.attachment
.view_format
.sample_type(None)
.sample_type(None, None)
.unwrap()
{
wgt::TextureSampleType::Float { .. } => vk::ClearColorValue {
Expand Down
Loading

0 comments on commit 32c5a22

Please sign in to comment.