diff --git a/CHANGELOG.md b/CHANGELOG.md index 9af353b393a..abccdca4a92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,10 @@ Bottom level categories: - Change `AdapterInfo::{device,vendor}` to be `u32` instead of `usize`. By @ameknite in [#3760](https://github.com/gfx-rs/wgpu/pull/3760) +#### DX12 + +- Increase the `max_storage_buffers_per_shader_stage` and `max_storage_textures_per_shader_stage` limits based on what the hardware supports. by @Elabajaba in [#3798]https://github.com/gfx-rs/wgpu/pull/3798 + ### Documentation #### General diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index 13530afb3eb..805d77376e7 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -74,6 +74,29 @@ impl super::Adapter { profiling::scope!("feature queries"); + // Detect the highest supported feature level. + let d3d_feature_level = [ + d3d12::FeatureLevel::L12_1, + d3d12::FeatureLevel::L12_0, + d3d12::FeatureLevel::L11_1, + d3d12::FeatureLevel::L11_0, + ]; + let mut device_levels: d3d12_ty::D3D12_FEATURE_DATA_FEATURE_LEVELS = + unsafe { mem::zeroed() }; + device_levels.NumFeatureLevels = d3d_feature_level.len() as u32; + device_levels.pFeatureLevelsRequested = d3d_feature_level.as_ptr().cast(); + unsafe { + device.CheckFeatureSupport( + d3d12_ty::D3D12_FEATURE_FEATURE_LEVELS, + &mut device_levels as *mut _ as *mut _, + mem::size_of::() as _, + ) + }; + // This cast should never fail because we only requested feature levels that are already in the enum. + let max_feature_level = + d3d12::FeatureLevel::try_from(device_levels.MaxSupportedFeatureLevel) + .expect("Unexpected feature level"); + // We have found a possible adapter. // Acquire the device information. let mut desc: dxgi1_2::DXGI_ADAPTER_DESC2 = unsafe { mem::zeroed() }; @@ -182,11 +205,18 @@ impl super::Adapter { // Theoretically vram limited, but in practice 2^20 is the limit let tier3_practical_descriptor_limit = 1 << 20; - let (full_heap_count, _uav_count) = match options.ResourceBindingTier { - d3d12_ty::D3D12_RESOURCE_BINDING_TIER_1 => ( - d3d12_ty::D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_1, - 8, // conservative, is 64 on feature level 11.1 - ), + let (full_heap_count, uav_count) = match options.ResourceBindingTier { + d3d12_ty::D3D12_RESOURCE_BINDING_TIER_1 => { + let uav_count = match max_feature_level { + d3d12::FeatureLevel::L11_0 => 8, + _ => 64, + }; + + ( + d3d12_ty::D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_1, + uav_count, + ) + } d3d12_ty::D3D12_RESOURCE_BINDING_TIER_2 => ( d3d12_ty::D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_2, 64, @@ -284,9 +314,10 @@ impl super::Adapter { _ => d3d12_ty::D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE, }, // these both account towards `uav_count`, but we can't express the limit as as sum - max_storage_buffers_per_shader_stage: base.max_storage_buffers_per_shader_stage, - max_storage_textures_per_shader_stage: base - .max_storage_textures_per_shader_stage, + // of the two, so we divide it by 4 to account for the worst case scenario + // (2 shader stages, with both using 16 storage textures and 16 storage buffers) + max_storage_buffers_per_shader_stage: uav_count / 4, + max_storage_textures_per_shader_stage: uav_count / 4, max_uniform_buffers_per_shader_stage: full_heap_count, max_uniform_buffer_binding_size: d3d12_ty::D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16, diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 3b6a10cd3d8..bf220967d70 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -844,7 +844,7 @@ pub struct Limits { pub max_samplers_per_shader_stage: u32, /// Amount of storage buffers visible in a single shader stage. Defaults to 8. Higher is "better". pub max_storage_buffers_per_shader_stage: u32, - /// Amount of storage textures visible in a single shader stage. Defaults to 8. Higher is "better". + /// Amount of storage textures visible in a single shader stage. Defaults to 4. Higher is "better". pub max_storage_textures_per_shader_stage: u32, /// Amount of uniform buffers visible in a single shader stage. Defaults to 12. Higher is "better". pub max_uniform_buffers_per_shader_stage: u32,