From 9f4af02661b81a87ca42607f21b00581298caf79 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Tue, 30 May 2023 06:38:54 -0400 Subject: [PATCH] DX12 increase `max_storage_buffers_per_shader_stage` and `max_storage_textures_per_shader_stage` (#3798) --- CHANGELOG.md | 6 +++++ wgpu-hal/src/dx12/adapter.rs | 47 ++++++++++++++++++++++++++++++------ wgpu-types/src/lib.rs | 2 +- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cf9e66c8a..62b3900601 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,12 @@ Bottom level categories: ## Unreleased +### Changes + +#### 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 + ## v0.16.1 (2023-05-24) ### Bug Fixes diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index fd7f2f926c..a25ef78ab3 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 98481be8b4..32b1bc47a2 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,