From c490293a99399c1b42adbf9fcfde282bb63ae4cb Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Mon, 6 Jan 2025 17:30:54 -0500 Subject: [PATCH] Raise Vulkan/DX12 `max_color_attachment_bytes_per_sample` Limit --- CHANGELOG.md | 2 ++ wgpu-core/src/validation.rs | 7 ++----- wgpu-hal/src/dx12/adapter.rs | 5 ++--- wgpu-hal/src/gles/adapter.rs | 5 +++-- wgpu-hal/src/vulkan/adapter.rs | 9 +++++++-- wgpu-types/src/lib.rs | 11 ++++++++++- 6 files changed, 26 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b1d58946a..f854564474 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -217,10 +217,12 @@ By @wumpf in [#6849](https://github.com/gfx-rs/wgpu/pull/6849). #### Vulkan - Allocate descriptors for acceleration structures. By @Vecvec in [#6861](https://github.com/gfx-rs/wgpu/pull/6861). +- `max_color_attachment_bytes_per_sample` is now correctly set to 128. By @cwfitzgerald in [#6866](https://github.com/gfx-rs/wgpu/pull/6866) #### D3D12 - Fix no longer showing software rasterizer adapters. By @wumpf in [#6843](https://github.com/gfx-rs/wgpu/pull/6843). +- `max_color_attachment_bytes_per_sample` is now correctly set to 128. By @cwfitzgerald in [#6866](https://github.com/gfx-rs/wgpu/pull/6866) ### Examples diff --git a/wgpu-core/src/validation.rs b/wgpu-core/src/validation.rs index 7755401a5c..be6abe9725 100644 --- a/wgpu-core/src/validation.rs +++ b/wgpu-core/src/validation.rs @@ -1295,7 +1295,7 @@ pub fn validate_color_attachment_bytes_per_sample( attachment_formats: impl Iterator>, limit: u32, ) -> Result<(), u32> { - let mut total_bytes_per_sample = 0; + let mut total_bytes_per_sample: u32 = 0; for format in attachment_formats { let Some(format) = format else { continue; @@ -1304,10 +1304,7 @@ pub fn validate_color_attachment_bytes_per_sample( let byte_cost = format.target_pixel_byte_cost().unwrap(); let alignment = format.target_component_alignment().unwrap(); - let rem = total_bytes_per_sample % alignment; - if rem != 0 { - total_bytes_per_sample += alignment - rem; - } + total_bytes_per_sample = total_bytes_per_sample.next_multiple_of(alignment); total_bytes_per_sample += byte_cost; } diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index e9be55c1f8..0ef706d8c8 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -425,9 +425,8 @@ impl super::Adapter { // See https://learn.microsoft.com/en-us/windows/win32/direct3d12/hardware-feature-levels#feature-level-support let max_color_attachments = 8; - // TODO: determine this programmatically if possible. - // https://github.com/gpuweb/gpuweb/issues/2965#issuecomment-1361315447 - let max_color_attachment_bytes_per_sample = 64; + let max_color_attachment_bytes_per_sample = + max_color_attachments * wgt::TextureFormat::MAX_TARGET_PIXEL_BYTE_COST; Some(crate::ExposedAdapter { adapter: super::Adapter { diff --git a/wgpu-hal/src/gles/adapter.rs b/wgpu-hal/src/gles/adapter.rs index a95511908e..15d171f55a 100644 --- a/wgpu-hal/src/gles/adapter.rs +++ b/wgpu-hal/src/gles/adapter.rs @@ -663,8 +663,9 @@ impl super::Adapter { .min(crate::MAX_COLOR_ATTACHMENTS as i32) as u32 }; - // TODO: programmatically determine this. - let max_color_attachment_bytes_per_sample = 32; + // 16 bytes per sample is the maximum size of a color attachment. + let max_color_attachment_bytes_per_sample = + max_color_attachments * wgt::TextureFormat::MAX_TARGET_PIXEL_BYTE_COST; let limits = wgt::Limits { max_texture_dimension_1d: max_texture_size, diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index ff56e38830..384471dde3 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -1052,8 +1052,13 @@ impl PhysicalDeviceProperties { // TODO: programmatically determine this, if possible. It's unclear whether we can // as of https://github.com/gpuweb/gpuweb/issues/2965#issuecomment-1361315447. - // We could increase the limit when we aren't on a tiled GPU. - let max_color_attachment_bytes_per_sample = 32; + // + // In theory some tilers may not support this much. We can't tell however, and + // the driver will throw a DEVICE_REMOVED if it goes too high in usage. This is fine. + // + // 16 bytes per sample is the maximum size for a color attachment. + let max_color_attachment_bytes_per_sample = + limits.max_color_attachments * wgt::TextureFormat::MAX_TARGET_PIXEL_BYTE_COST; wgt::Limits { max_texture_dimension_1d: limits.max_image_dimension1_d, diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 48ec0bfaaa..b8435aa302 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -1192,7 +1192,10 @@ pub struct Limits { /// The maximum allowed number of color attachments. pub max_color_attachments: u32, /// The maximum number of bytes necessary to hold one sample (pixel or subpixel) of render - /// pipeline output data, across all color attachments. + /// pipeline output data, across all color attachments as described by [`TextureFormat::target_pixel_byte_cost`] + /// and [`TextureFormat::target_component_alignment`]. Defaults to 32. Higher is "better". + /// + /// ⚠️ `Rgba8Unorm`/`Rgba8Snorm`/`Bgra8Unorm`/`Bgra8Snorm` are deceptively 8 bytes per sample. ⚠️ pub max_color_attachment_bytes_per_sample: u32, /// Maximum number of bytes used for workgroup memory in a compute entry point. Defaults to /// 16384. Higher is "better". @@ -3775,6 +3778,9 @@ impl TextureFormat { } } + /// The largest number that can be returned by [`Self::target_pixel_byte_cost`]. + pub const MAX_TARGET_PIXEL_BYTE_COST: u32 = 16; + /// The number of bytes occupied per pixel in a color attachment /// #[must_use] @@ -3800,11 +3806,13 @@ impl TextureFormat { | Self::R32Uint | Self::R32Sint | Self::R32Float => Some(4), + // Despite being 4 bytes per pixel, these are 8 bytes per pixel in the table Self::Rgba8Unorm | Self::Rgba8UnormSrgb | Self::Rgba8Snorm | Self::Bgra8Unorm | Self::Bgra8UnormSrgb + // --- | Self::Rgba16Uint | Self::Rgba16Sint | Self::Rgba16Unorm @@ -3817,6 +3825,7 @@ impl TextureFormat { | Self::Rgb10a2Unorm | Self::Rg11b10Ufloat => Some(8), Self::Rgba32Uint | Self::Rgba32Sint | Self::Rgba32Float => Some(16), + // ⚠️ If you add formats with larger sizes, make sure you change `MAX_TARGET_PIXEL_BYTE_COST`` ⚠️ Self::Stencil8 | Self::Depth16Unorm | Self::Depth24Plus