Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple Fixes to Format Feature Detection #2856

Merged
merged 7 commits into from
Jul 6, 2022
10 changes: 8 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,22 @@ Bottom level categories:
## Unreleased

### Bug Fixes

#### General
- Prefer `DeviceType::DiscreteGpu` over `DeviceType::Other` for `PowerPreference::LowPower` so Vulkan is preferred over OpenGL again by @Craig-Macomber in [#2853](https://github.com/gfx-rs/wgpu/pull/2853)
- Allow running `get_texture_format_features` on unsupported texture formats (returning no flags) by @cwfitzgerald in [#2856](https://github.com/gfx-rs/wgpu/pull/2856)
- Allow multi-sampled textures that are supported by the device but not WebGPU if `TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES` is enabled by @cwfitzgerald in [#2856](https://github.com/gfx-rs/wgpu/pull/2856)
- `get_texture_format_features` only lists the COPY_* usages if the adapter actually supports that usage by @cwfitzgerald in [#2856](https://github.com/gfx-rs/wgpu/pull/2856)

#### DX12
- `DownlevelCapabilities::default()` now returns the `ANISOTROPIC_FILTERING` flag set to true so DX12 lists `ANISOTROPIC_FILTERING` as true again by @cwfitzgerald in [#2851](https://github.com/gfx-rs/wgpu/pull/2851)
- Properly query format features for UAV/SRV usages of depth formats by @cwfitzgerald in [#2856](https://github.com/gfx-rs/wgpu/pull/2856)

#### GLES
- gl: fix depth stencil texture format capability by @jinleili in [#2854](https://github.com/gfx-rs/wgpu/pull/2854)
- Fix depth stencil texture format capability by @jinleili in [#2854](https://github.com/gfx-rs/wgpu/pull/2854)
- `get_texture_format_features` now only returns usages for formats it actually supports by @cwfitzgerald in [#2856](https://github.com/gfx-rs/wgpu/pull/2856)

### Documentation

- Update present_mode docs as most of them don't automatically fall back to Fifo anymore. by @Elabajaba in [#2855](https://github.com/gfx-rs/wgpu/pull/2855)

## wgpu-0.13.1 (2022-07-02)
Expand Down
11 changes: 5 additions & 6 deletions wgpu-core/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,10 @@ impl<A: HalApi> Device<A> {
}
}

let format_features = self
.describe_format_features(adapter, desc.format)
.map_err(|error| CreateTextureError::MissingFeatures(desc.format, error))?;

if desc.sample_count > 1 {
if desc.mip_level_count != 1 {
return Err(CreateTextureError::InvalidMipLevelCount {
Expand All @@ -775,8 +779,7 @@ impl<A: HalApi> Device<A> {
return Err(CreateTextureError::MultisampledNotRenderAttachment);
}

if !format_desc
.guaranteed_format_features
if !format_features
.flags
.contains(wgt::TextureFormatFeatureFlags::MULTISAMPLE)
{
Expand All @@ -793,10 +796,6 @@ impl<A: HalApi> Device<A> {
});
}

let format_features = self
.describe_format_features(adapter, desc.format)
.map_err(|error| CreateTextureError::MissingFeatures(desc.format, error))?;

let missing_allowed_usages = desc.usage - format_features.allowed_usages;
if !missing_allowed_usages.is_empty() {
return Err(CreateTextureError::InvalidFormatUsages(
Expand Down
4 changes: 3 additions & 1 deletion wgpu-core/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,10 @@ impl<A: HalApi> Adapter<A> {
use hal::TextureFormatCapabilities as Tfc;

let caps = unsafe { self.raw.adapter.texture_format_capabilities(format) };
let mut allowed_usages = format.describe().guaranteed_format_features.allowed_usages;
let mut allowed_usages = wgt::TextureUsages::empty();

allowed_usages.set(wgt::TextureUsages::COPY_SRC, caps.contains(Tfc::COPY_SRC));
allowed_usages.set(wgt::TextureUsages::COPY_DST, caps.contains(Tfc::COPY_DST));
allowed_usages.set(
wgt::TextureUsages::TEXTURE_BINDING,
caps.contains(Tfc::SAMPLED),
Expand Down
13 changes: 10 additions & 3 deletions wgpu-hal/src/auxil/dxgi/conv.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use winapi::shared::dxgiformat;

pub fn map_texture_format(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT {
pub fn map_texture_format_failable(format: wgt::TextureFormat) -> Option<dxgiformat::DXGI_FORMAT> {
use wgt::TextureFormat as Tf;
use winapi::shared::dxgiformat::*;

match format {
Some(match format {
Tf::R8Unorm => DXGI_FORMAT_R8_UNORM,
Tf::R8Snorm => DXGI_FORMAT_R8_SNORM,
Tf::R8Uint => DXGI_FORMAT_R8_UINT,
Expand Down Expand Up @@ -78,7 +78,14 @@ pub fn map_texture_format(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT
| Tf::Astc {
block: _,
channel: _,
} => unreachable!(),
} => return None,
})
}

pub fn map_texture_format(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT {
match map_texture_format_failable(format) {
Some(f) => f,
None => unreachable!(),
}
}

Expand Down
43 changes: 37 additions & 6 deletions wgpu-hal/src/dx12/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,12 @@ impl crate::Adapter<super::Api> for super::Adapter {
) -> crate::TextureFormatCapabilities {
use crate::TextureFormatCapabilities as Tfc;

let raw_format = auxil::dxgi::conv::map_texture_format(format);
let raw_format = match auxil::dxgi::conv::map_texture_format_failable(format) {
Some(f) => f,
None => return Tfc::empty(),
};
let no_depth_format = auxil::dxgi::conv::map_texture_format_nodepth(format);

let mut data = d3d12::D3D12_FEATURE_DATA_FORMAT_SUPPORT {
Format: raw_format,
Support1: mem::zeroed(),
Expand All @@ -351,20 +356,43 @@ impl crate::Adapter<super::Api> for super::Adapter {
)
);

// Because we use a different format for SRV and UAV views of depth textures, we need to check
// the features that use SRV/UAVs using the no-depth format.
let mut data_no_depth = d3d12::D3D12_FEATURE_DATA_FORMAT_SUPPORT {
Format: no_depth_format,
Support1: mem::zeroed(),
Support2: mem::zeroed(),
};
if raw_format != no_depth_format {
// Only-recheck if we're using a different format
assert_eq!(
winerror::S_OK,
self.device.CheckFeatureSupport(
d3d12::D3D12_FEATURE_FORMAT_SUPPORT,
&mut data_no_depth as *mut _ as *mut _,
mem::size_of::<d3d12::D3D12_FEATURE_DATA_FORMAT_SUPPORT>() as _,
)
);
} else {
// Same format, just copy over.
data_no_depth = data;
}

let mut caps = Tfc::COPY_SRC | Tfc::COPY_DST;
let is_texture = data.Support1
& (d3d12::D3D12_FORMAT_SUPPORT1_TEXTURE1D
| d3d12::D3D12_FORMAT_SUPPORT1_TEXTURE2D
| d3d12::D3D12_FORMAT_SUPPORT1_TEXTURE3D
| d3d12::D3D12_FORMAT_SUPPORT1_TEXTURECUBE)
!= 0;
// SRVs use no-depth format
caps.set(
Tfc::SAMPLED,
is_texture && data.Support1 & d3d12::D3D12_FORMAT_SUPPORT1_SHADER_LOAD != 0,
is_texture && data_no_depth.Support1 & d3d12::D3D12_FORMAT_SUPPORT1_SHADER_LOAD != 0,
);
caps.set(
Tfc::SAMPLED_LINEAR,
data.Support1 & d3d12::D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE != 0,
data_no_depth.Support1 & d3d12::D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE != 0,
);
caps.set(
Tfc::COLOR_ATTACHMENT,
Expand All @@ -378,17 +406,20 @@ impl crate::Adapter<super::Api> for super::Adapter {
Tfc::DEPTH_STENCIL_ATTACHMENT,
data.Support1 & d3d12::D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL != 0,
);
// UAVs use no-depth format
caps.set(
Tfc::STORAGE,
data.Support1 & d3d12::D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW != 0,
data_no_depth.Support1 & d3d12::D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW != 0,
);
caps.set(
Tfc::STORAGE_READ_WRITE,
data.Support2 & d3d12::D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD != 0,
data_no_depth.Support2 & d3d12::D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD != 0,
);

// We load via UAV/SRV so use no-depth
let no_msaa_load = caps.contains(Tfc::SAMPLED)
&& data.Support1 & d3d12::D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD == 0;
&& data_no_depth.Support1 & d3d12::D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD == 0;

let no_msaa_target = data.Support1
& (d3d12::D3D12_FORMAT_SUPPORT1_RENDER_TARGET
| d3d12::D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL)
Expand Down
66 changes: 39 additions & 27 deletions wgpu-hal/src/gles/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,7 @@ impl super::Adapter {
context,
private_caps,
workarounds,
features,
shading_language_version,
max_texture_size,
}),
Expand Down Expand Up @@ -639,34 +640,45 @@ impl crate::Adapter<super::Api> for super::Adapter {
// The storage types are based on table 8.26, in section
// "TEXTURE IMAGE LOADS AND STORES" of OpenGLES-3.2 spec.
let empty = Tfc::empty();
let unfilterable = Tfc::SAMPLED;
let depth = Tfc::SAMPLED | Tfc::MULTISAMPLE | Tfc::DEPTH_STENCIL_ATTACHMENT;
let base = Tfc::COPY_SRC | Tfc::COPY_DST;
let unfilterable = base | Tfc::SAMPLED;
let depth = base | Tfc::SAMPLED | Tfc::MULTISAMPLE | Tfc::DEPTH_STENCIL_ATTACHMENT;
let filterable = unfilterable | Tfc::SAMPLED_LINEAR;
let renderable =
unfilterable | Tfc::COLOR_ATTACHMENT | Tfc::MULTISAMPLE | Tfc::MULTISAMPLE_RESOLVE;
let filterable_renderable = filterable | renderable | Tfc::COLOR_ATTACHMENT_BLEND;
let storage = Tfc::STORAGE | Tfc::STORAGE_READ_WRITE;
let storage = base | Tfc::STORAGE | Tfc::STORAGE_READ_WRITE;

let half_float_renderable = if self
.shared
.private_caps
.contains(super::PrivateCapabilities::COLOR_BUFFER_HALF_FLOAT)
{
Tfc::COLOR_ATTACHMENT | Tfc::COLOR_ATTACHMENT_BLEND
} else {
Tfc::empty()
let feature_fn = |f, caps| {
if self.shared.features.contains(f) {
caps
} else {
empty
}
};

let float_renderable = if self
.shared
.private_caps
.contains(super::PrivateCapabilities::COLOR_BUFFER_FLOAT)
{
Tfc::COLOR_ATTACHMENT | Tfc::COLOR_ATTACHMENT_BLEND
} else {
Tfc::empty()
let bcn_features = feature_fn(wgt::Features::TEXTURE_COMPRESSION_BC, filterable);
let etc2_features = feature_fn(wgt::Features::TEXTURE_COMPRESSION_ETC2, filterable);
let astc_features = feature_fn(wgt::Features::TEXTURE_COMPRESSION_ASTC_LDR, filterable);

let private_caps_fn = |f, caps| {
if self.shared.private_caps.contains(f) {
caps
} else {
empty
}
};

let half_float_renderable = private_caps_fn(
super::PrivateCapabilities::COLOR_BUFFER_HALF_FLOAT,
Tfc::COLOR_ATTACHMENT | Tfc::COLOR_ATTACHMENT_BLEND,
);

let float_renderable = private_caps_fn(
super::PrivateCapabilities::COLOR_BUFFER_FLOAT,
Tfc::COLOR_ATTACHMENT | Tfc::COLOR_ATTACHMENT_BLEND,
);

match format {
Tf::R8Unorm => filterable_renderable,
Tf::R8Snorm => filterable,
Expand Down Expand Up @@ -712,8 +724,8 @@ impl crate::Adapter<super::Api> for super::Adapter {
| Tf::Depth24Plus
| Tf::Depth24PlusStencil8
| Tf::Depth24UnormStencil8 => depth,
Tf::Rgb9e5Ufloat
| Tf::Bc1RgbaUnorm
Tf::Rgb9e5Ufloat => filterable,
Tf::Bc1RgbaUnorm
| Tf::Bc1RgbaUnormSrgb
| Tf::Bc2RgbaUnorm
| Tf::Bc2RgbaUnormSrgb
Expand All @@ -726,8 +738,8 @@ impl crate::Adapter<super::Api> for super::Adapter {
| Tf::Bc6hRgbSfloat
| Tf::Bc6hRgbUfloat
| Tf::Bc7RgbaUnorm
| Tf::Bc7RgbaUnormSrgb
| Tf::Etc2Rgb8Unorm
| Tf::Bc7RgbaUnormSrgb => bcn_features,
Tf::Etc2Rgb8Unorm
| Tf::Etc2Rgb8UnormSrgb
| Tf::Etc2Rgb8A1Unorm
| Tf::Etc2Rgb8A1UnormSrgb
Expand All @@ -736,15 +748,15 @@ impl crate::Adapter<super::Api> for super::Adapter {
| Tf::EacR11Unorm
| Tf::EacR11Snorm
| Tf::EacRg11Unorm
| Tf::EacRg11Snorm
| Tf::Astc {
| Tf::EacRg11Snorm => etc2_features,
Tf::Astc {
block: _,
channel: AstcChannel::Unorm | AstcChannel::UnormSrgb,
} => filterable,
} => astc_features,
Tf::Astc {
block: _,
channel: AstcChannel::Hdr,
} => empty,
} => Tfc::empty(),
}
}

Expand Down
1 change: 1 addition & 0 deletions wgpu-hal/src/gles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ struct TextureFormatDesc {
struct AdapterShared {
context: AdapterContext,
private_caps: PrivateCapabilities,
features: wgt::Features,
workarounds: Workarounds,
shading_language_version: naga::back::glsl::Version,
max_texture_size: u32,
Expand Down
7 changes: 5 additions & 2 deletions wgpu-hal/src/vulkan/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1459,8 +1459,11 @@ impl crate::Adapter<super::Api> for super::Adapter {
let properties = self
.phd_capabilities
.formats
.get(vk_format.as_raw() as usize)
.unwrap();
.get(vk_format.as_raw() as usize);
let properties = match properties {
Some(p) => p,
None => return Tfc::empty(),
};
let features = properties.optimal_tiling_features;

let mut flags = Tfc::empty();
Expand Down
Loading