From f55db4fda181a5b333fb4421c167606e68033d95 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Sat, 26 Nov 2022 21:22:27 +0800 Subject: [PATCH 01/20] Add `view_formats` in TextureDescriptor --- wgpu-core/src/device/mod.rs | 25 ++++++++++++---- wgpu-core/src/present.rs | 1 + wgpu-core/src/resource.rs | 2 ++ wgpu-types/src/lib.rs | 30 ++++++++++++++++++- wgpu/examples/bunnymark/main.rs | 1 + wgpu/examples/capture/main.rs | 1 + wgpu/examples/conservative-raster/main.rs | 1 + wgpu/examples/cube/main.rs | 1 + wgpu/examples/framework.rs | 1 + wgpu/examples/mipmap/main.rs | 1 + wgpu/examples/msaa-line/main.rs | 1 + wgpu/examples/shadow/main.rs | 2 ++ wgpu/examples/skybox/main.rs | 2 ++ wgpu/examples/texture-arrays/main.rs | 5 ++++ wgpu/examples/water/main.rs | 2 ++ wgpu/tests/clear_texture.rs | 1 + wgpu/tests/queue_transfer.rs | 1 + wgpu/tests/resource_error.rs | 1 + wgpu/tests/shader_primitive_index/mod.rs | 1 + wgpu/tests/texture_bounds.rs | 1 + wgpu/tests/vertex_indices/mod.rs | 1 + wgpu/tests/write_texture.rs | 1 + wgpu/tests/zero_init_texture_after_discard.rs | 1 + 23 files changed, 78 insertions(+), 6 deletions(-) diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index db691f2e55..df8a2d0618 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -852,7 +852,16 @@ impl Device { )); } - // TODO: validate missing TextureDescriptor::view_formats. + if let Some(ref view_formats) = desc.view_formats { + for format in view_formats { + if desc.format == *format { + continue; + } + if desc.format.remove_srgb_suffix() != format.remove_srgb_suffix() { + return Err(CreateTextureError::InvalidViewFormat(*format, desc.format)); + } + } + } // Enforce having COPY_DST/DEPTH_STENCIL_WRIT/COLOR_TARGET otherwise we // wouldn't be able to initialize the texture. @@ -1086,10 +1095,16 @@ impl Device { } let format = desc.format.unwrap_or(texture.desc.format); if format != texture.desc.format { - return Err(resource::CreateTextureViewError::FormatReinterpretation { - texture: texture.desc.format, - view: format, - }); + let compatible = match texture.desc.view_formats { + Some(ref view_formats) => view_formats.contains(&format), + None => false, + }; + if !compatible { + return Err(resource::CreateTextureViewError::FormatReinterpretation { + texture: texture.desc.format, + view: format, + }); + } } // filter the usages based on the other criteria diff --git a/wgpu-core/src/present.rs b/wgpu-core/src/present.rs index 41da2fa585..c1afb5e97c 100644 --- a/wgpu-core/src/present.rs +++ b/wgpu-core/src/present.rs @@ -180,6 +180,7 @@ impl Global { format: config.format, dimension: wgt::TextureDimension::D2, usage: config.usage, + view_formats: None, }, hal_usage: conv::map_texture_usage(config.usage, config.format.into()), format_features: wgt::TextureFormatFeatures { diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index 38a50a62c7..00758d70b0 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -507,6 +507,8 @@ pub enum CreateTextureError { if *.2 { " due to downlevel restrictions" } else { "" } )] InvalidFormatUsages(wgt::TextureUsages, wgt::TextureFormat, bool), + #[error("The view format {0:?} is not compatible with texture format {1:?}.")] + InvalidViewFormat(wgt::TextureFormat, wgt::TextureFormat), #[error("Texture usages {0:?} are not allowed on a texture of dimensions {1:?}")] InvalidDimensionUsages(wgt::TextureUsages, wgt::TextureDimension), #[error("Texture usage STORAGE_BINDING is not allowed for multisampled textures")] diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 681256e938..d483e33900 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -2537,6 +2537,29 @@ impl TextureFormat { }, } } + + /// Get texture view format compatible none `Srgb` suffix format. + pub fn remove_srgb_suffix(&self) -> TextureFormat { + match *self { + Self::Rgba8UnormSrgb => Self::Rgba8Unorm, + Self::Bgra8UnormSrgb => Self::Bgra8Unorm, + Self::Bc1RgbaUnormSrgb => Self::Bc1RgbaUnorm, + Self::Bc2RgbaUnormSrgb => Self::Bc2RgbaUnorm, + Self::Bc3RgbaUnormSrgb => Self::Bc3RgbaUnorm, + Self::Bc7RgbaUnormSrgb => Self::Bc7RgbaUnorm, + Self::Etc2Rgb8UnormSrgb => Self::Etc2Rgb8Unorm, + Self::Etc2Rgb8A1UnormSrgb => Self::Etc2Rgb8A1Unorm, + Self::Etc2Rgba8UnormSrgb => Self::Etc2Rgba8Unorm, + Self::Astc { + block, + channel: AstcChannel::UnormSrgb, + } => Self::Astc { + block, + channel: AstcChannel::Unorm, + }, + _ => *self, + } + } } #[test] @@ -4336,7 +4359,10 @@ pub struct TextureDescriptor { pub format: TextureFormat, /// Allowed usages of the texture. If used in other ways, the operation will panic. pub usage: TextureUsages, - // TODO: missing view_formats https://www.w3.org/TR/webgpu/#dom-gputexturedescriptor-viewformats + /// Specifies what view format values will be allowed when calling create_view() on this texture. + /// Note: Adding a format to this list may have a significant performance impact, + /// so it is best to avoid adding formats unnecessarily. + pub view_formats: Option>, } impl TextureDescriptor { @@ -4350,6 +4376,7 @@ impl TextureDescriptor { dimension: self.dimension, format: self.format, usage: self.usage, + view_formats: self.view_formats.clone(), } } @@ -4370,6 +4397,7 @@ impl TextureDescriptor { /// dimension: wgpu::TextureDimension::D3, /// format: wgpu::TextureFormat::Rgba8Sint, /// usage: wgpu::TextureUsages::empty(), + /// view_formats: None /// }; /// /// assert_eq!(desc.mip_level_size(0), Some(wgpu::Extent3d { width: 100, height: 60, depth_or_array_layers: 1 })); diff --git a/wgpu/examples/bunnymark/main.rs b/wgpu/examples/bunnymark/main.rs index c7383e0296..871c45818f 100644 --- a/wgpu/examples/bunnymark/main.rs +++ b/wgpu/examples/bunnymark/main.rs @@ -152,6 +152,7 @@ impl framework::Example for Example { dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8UnormSrgb, usage: wgpu::TextureUsages::COPY_DST | wgpu::TextureUsages::TEXTURE_BINDING, + view_formats: None, }); queue.write_texture( texture.as_image_copy(), diff --git a/wgpu/examples/capture/main.rs b/wgpu/examples/capture/main.rs index 747b361de2..46e90d1a0b 100644 --- a/wgpu/examples/capture/main.rs +++ b/wgpu/examples/capture/main.rs @@ -83,6 +83,7 @@ async fn create_red_image_with_dimensions( format: wgpu::TextureFormat::Rgba8UnormSrgb, usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC, label: None, + view_formats: None, }); // Set the background to be red diff --git a/wgpu/examples/conservative-raster/main.rs b/wgpu/examples/conservative-raster/main.rs index 2fc4e98676..fb1ea12a6d 100644 --- a/wgpu/examples/conservative-raster/main.rs +++ b/wgpu/examples/conservative-raster/main.rs @@ -36,6 +36,7 @@ impl Example { format: RENDER_TARGET_FORMAT, usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::RENDER_ATTACHMENT, + view_formats: None, }) .create_view(&Default::default()); diff --git a/wgpu/examples/cube/main.rs b/wgpu/examples/cube/main.rs index d029f7035e..d2c3315a68 100644 --- a/wgpu/examples/cube/main.rs +++ b/wgpu/examples/cube/main.rs @@ -202,6 +202,7 @@ impl framework::Example for Example { dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::R8Uint, usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, + view_formats: None, }); let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default()); queue.write_texture( diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index 9af044bf66..b0ae02a00a 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -523,6 +523,7 @@ pub fn test(mut params: FrameworkRefTest) { dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8UnormSrgb, usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC, + view_formats: None, }); let dst_view = dst_texture.create_view(&wgpu::TextureViewDescriptor::default()); diff --git a/wgpu/examples/mipmap/main.rs b/wgpu/examples/mipmap/main.rs index f1cac82e9c..9985fd8867 100644 --- a/wgpu/examples/mipmap/main.rs +++ b/wgpu/examples/mipmap/main.rs @@ -232,6 +232,7 @@ impl framework::Example for Example { | wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_DST, label: None, + view_formats: None, }); let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default()); //Note: we could use queue.write_texture instead, and this is what other diff --git a/wgpu/examples/msaa-line/main.rs b/wgpu/examples/msaa-line/main.rs index 5817b13ced..0a24c2be00 100644 --- a/wgpu/examples/msaa-line/main.rs +++ b/wgpu/examples/msaa-line/main.rs @@ -109,6 +109,7 @@ impl Example { format: config.format, usage: wgpu::TextureUsages::RENDER_ATTACHMENT, label: None, + view_formats: None, }; device diff --git a/wgpu/examples/shadow/main.rs b/wgpu/examples/shadow/main.rs index 85cff2af47..c217d423ba 100644 --- a/wgpu/examples/shadow/main.rs +++ b/wgpu/examples/shadow/main.rs @@ -197,6 +197,7 @@ impl Example { format: Self::DEPTH_FORMAT, usage: wgpu::TextureUsages::RENDER_ATTACHMENT, label: None, + view_formats: None, }); depth_texture.create_view(&wgpu::TextureViewDescriptor::default()) @@ -385,6 +386,7 @@ impl framework::Example for Example { format: Self::SHADOW_FORMAT, usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING, label: None, + view_formats: None, }); let shadow_view = shadow_texture.create_view(&wgpu::TextureViewDescriptor::default()); diff --git a/wgpu/examples/skybox/main.rs b/wgpu/examples/skybox/main.rs index 987a4ebaa9..b9cfd9f0cb 100644 --- a/wgpu/examples/skybox/main.rs +++ b/wgpu/examples/skybox/main.rs @@ -85,6 +85,7 @@ impl Skybox { format: Self::DEPTH_FORMAT, usage: wgpu::TextureUsages::RENDER_ATTACHMENT, label: None, + view_formats: None, }); depth_texture.create_view(&wgpu::TextureViewDescriptor::default()) @@ -328,6 +329,7 @@ impl framework::Example for Skybox { format: skybox_format, usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, label: None, + view_formats: None, }, &image.data, ); diff --git a/wgpu/examples/texture-arrays/main.rs b/wgpu/examples/texture-arrays/main.rs index 89093b6400..6717a7b4f1 100644 --- a/wgpu/examples/texture-arrays/main.rs +++ b/wgpu/examples/texture-arrays/main.rs @@ -164,21 +164,26 @@ impl framework::Example for Example { format: wgpu::TextureFormat::Rgba8UnormSrgb, usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, label: None, + view_formats: None, }; let red_texture = device.create_texture(&wgpu::TextureDescriptor { label: Some("red"), + view_formats: None, ..texture_descriptor }); let green_texture = device.create_texture(&wgpu::TextureDescriptor { label: Some("green"), + view_formats: None, ..texture_descriptor }); let blue_texture = device.create_texture(&wgpu::TextureDescriptor { label: Some("blue"), + view_formats: None, ..texture_descriptor }); let white_texture = device.create_texture(&wgpu::TextureDescriptor { label: Some("white"), + view_formats: None, ..texture_descriptor }); diff --git a/wgpu/examples/water/main.rs b/wgpu/examples/water/main.rs index 3eb08940b9..37f2e8d392 100644 --- a/wgpu/examples/water/main.rs +++ b/wgpu/examples/water/main.rs @@ -197,6 +197,7 @@ impl Example { usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST | wgpu::TextureUsages::RENDER_ATTACHMENT, + view_formats: None, }); let draw_depth_buffer = device.create_texture(&wgpu::TextureDescriptor { @@ -209,6 +210,7 @@ impl Example { usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST | wgpu::TextureUsages::RENDER_ATTACHMENT, + view_formats: None, }); let color_sampler = device.create_sampler(&wgpu::SamplerDescriptor { diff --git a/wgpu/tests/clear_texture.rs b/wgpu/tests/clear_texture.rs index 3afdd98009..6de80cc428 100644 --- a/wgpu/tests/clear_texture.rs +++ b/wgpu/tests/clear_texture.rs @@ -225,6 +225,7 @@ fn single_texture_clear_test( // Forces internally the required usages to be able to clear it. // This is not visible on the API level. usage: wgpu::TextureUsages::TEXTURE_BINDING, + view_formats: None, }); let mut encoder = ctx .device diff --git a/wgpu/tests/queue_transfer.rs b/wgpu/tests/queue_transfer.rs index 90310ea6e7..1ded69882b 100644 --- a/wgpu/tests/queue_transfer.rs +++ b/wgpu/tests/queue_transfer.rs @@ -21,6 +21,7 @@ fn queue_write_texture_overflow() { dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba32Float, usage: wgpu::TextureUsages::COPY_DST, + view_formats: None, }); let data = vec![255; 128]; diff --git a/wgpu/tests/resource_error.rs b/wgpu/tests/resource_error.rs index 716c646a7d..672cbd72a3 100644 --- a/wgpu/tests/resource_error.rs +++ b/wgpu/tests/resource_error.rs @@ -44,6 +44,7 @@ fn bad_texture() { dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8UnormSrgb, usage: wgpu::TextureUsages::all(), + view_formats: None, }) }); diff --git a/wgpu/tests/shader_primitive_index/mod.rs b/wgpu/tests/shader_primitive_index/mod.rs index a7f68936f2..08b348e3e5 100644 --- a/wgpu/tests/shader_primitive_index/mod.rs +++ b/wgpu/tests/shader_primitive_index/mod.rs @@ -165,6 +165,7 @@ fn pulling_common( dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8Unorm, usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC, + view_formats: None, }); let color_view = color_texture.create_view(&wgpu::TextureViewDescriptor::default()); diff --git a/wgpu/tests/texture_bounds.rs b/wgpu/tests/texture_bounds.rs index 635dac8480..f302f066be 100644 --- a/wgpu/tests/texture_bounds.rs +++ b/wgpu/tests/texture_bounds.rs @@ -103,6 +103,7 @@ const TEXTURE_DESCRIPTOR: wgpu::TextureDescriptor = wgpu::TextureDescriptor { dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8UnormSrgb, usage: wgpu::TextureUsages::COPY_DST.union(wgpu::TextureUsages::COPY_SRC), + view_formats: None, }; const BYTES_PER_PIXEL: u32 = 4; diff --git a/wgpu/tests/vertex_indices/mod.rs b/wgpu/tests/vertex_indices/mod.rs index 2c739e8b3d..706d780cdb 100644 --- a/wgpu/tests/vertex_indices/mod.rs +++ b/wgpu/tests/vertex_indices/mod.rs @@ -97,6 +97,7 @@ fn pulling_common( dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8Unorm, usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_DST, + view_formats: None, }, &[0, 0, 0, 1], ) diff --git a/wgpu/tests/write_texture.rs b/wgpu/tests/write_texture.rs index 9d351ed70c..face573e1f 100644 --- a/wgpu/tests/write_texture.rs +++ b/wgpu/tests/write_texture.rs @@ -25,6 +25,7 @@ fn write_texture_subset() { | wgpu::TextureUsages::TEXTURE_BINDING, mip_level_count: 1, sample_count: 1, + view_formats: None, }); let data = vec![1u8; size as usize * 2]; // Write the first two rows diff --git a/wgpu/tests/zero_init_texture_after_discard.rs b/wgpu/tests/zero_init_texture_after_discard.rs index 751ae2aa77..0672c21176 100644 --- a/wgpu/tests/zero_init_texture_after_discard.rs +++ b/wgpu/tests/zero_init_texture_after_discard.rs @@ -208,6 +208,7 @@ fn create_white_texture_and_readback_buffer( | wgpu::TextureUsages::COPY_SRC | wgpu::TextureUsages::RENDER_ATTACHMENT }, + view_formats: None, }); // Clear using a write_texture operation. We could also clear using a render_pass clear. From aeb2c885224a16379fbf2f11a113647e4f5eaa9c Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Sat, 26 Nov 2022 21:33:59 +0800 Subject: [PATCH 02/20] Fix build deno failure --- deno_webgpu/src/texture.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/deno_webgpu/src/texture.rs b/deno_webgpu/src/texture.rs index db3c1143fe..52598b64cc 100644 --- a/deno_webgpu/src/texture.rs +++ b/deno_webgpu/src/texture.rs @@ -55,6 +55,7 @@ pub fn op_webgpu_create_texture( dimension: args.dimension, format: args.format, usage: wgpu_types::TextureUsages::from_bits_truncate(args.usage), + view_formats: None, }; gfx_put!(device => instance.device_create_texture( From 0a08124bf3c6ba4efb9c6d2d52d5a6c62353fc38 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Sun, 27 Nov 2022 09:31:09 +0800 Subject: [PATCH 03/20] Update wgpu-types/src/lib.rs Co-authored-by: Connor Fitzgerald --- wgpu-types/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index d483e33900..dd1ac41f8a 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -2538,7 +2538,7 @@ impl TextureFormat { } } - /// Get texture view format compatible none `Srgb` suffix format. + /// Strips the `Srgb` suffix from the given texture format. pub fn remove_srgb_suffix(&self) -> TextureFormat { match *self { Self::Rgba8UnormSrgb => Self::Rgba8Unorm, From e85f1b196e0d794a7fa9403c26ed0d58ccea9225 Mon Sep 17 00:00:00 2001 From: crowlkats Date: Sun, 27 Nov 2022 06:56:34 +0100 Subject: [PATCH 04/20] implement deno part --- deno_webgpu/src/02_idl_types.js | 9 +++++++++ deno_webgpu/src/texture.rs | 3 ++- deno_webgpu/webgpu.idl | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/deno_webgpu/src/02_idl_types.js b/deno_webgpu/src/02_idl_types.js index 1308834b19..9a6e66c627 100644 --- a/deno_webgpu/src/02_idl_types.js +++ b/deno_webgpu/src/02_idl_types.js @@ -427,6 +427,15 @@ converter: webidl.converters["GPUTextureUsageFlags"], required: true, }, + { + key: "viewFormats", + converter: webidl.createSequenceConverter( + webidl.converters["GPUTextureFormat"], + ), + get defaultValue() { + return []; + }, + }, ]; webidl.converters["GPUTextureDescriptor"] = webidl.createDictionaryConverter( "GPUTextureDescriptor", diff --git a/deno_webgpu/src/texture.rs b/deno_webgpu/src/texture.rs index 52598b64cc..5bc1d9d4f5 100644 --- a/deno_webgpu/src/texture.rs +++ b/deno_webgpu/src/texture.rs @@ -34,6 +34,7 @@ pub struct CreateTextureArgs { dimension: wgpu_types::TextureDimension, format: wgpu_types::TextureFormat, usage: u32, + view_formats: Vec, } #[op] @@ -55,7 +56,7 @@ pub fn op_webgpu_create_texture( dimension: args.dimension, format: args.format, usage: wgpu_types::TextureUsages::from_bits_truncate(args.usage), - view_formats: None, + view_formats: Some(args.view_formats), }; gfx_put!(device => instance.device_create_texture( diff --git a/deno_webgpu/webgpu.idl b/deno_webgpu/webgpu.idl index 7d5da0a878..7d23c29c34 100644 --- a/deno_webgpu/webgpu.idl +++ b/deno_webgpu/webgpu.idl @@ -200,6 +200,7 @@ dictionary GPUTextureDescriptor : GPUObjectDescriptorBase { GPUTextureDimension dimension = "2d"; required GPUTextureFormat format; required GPUTextureUsageFlags usage; + sequence viewFormats = []; }; enum GPUTextureDimension { From 924e216c6dc1b2fc39ec7159e512e4ec7f946c6a Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Mon, 28 Nov 2022 09:06:11 +0800 Subject: [PATCH 05/20] Change `Option>` to `& [TextureFormat]` --- deno_webgpu/src/texture.rs | 2 +- wgpu-core/src/device/mod.rs | 30 +++++++---------- wgpu-core/src/present.rs | 2 +- wgpu-core/src/resource.rs | 2 +- wgpu-hal/src/gles/adapter.rs | 3 +- wgpu-types/src/lib.rs | 11 ++++--- wgpu/examples/bunnymark/main.rs | 2 +- wgpu/examples/capture/main.rs | 2 +- wgpu/examples/conservative-raster/main.rs | 2 +- wgpu/examples/cube/main.rs | 2 +- wgpu/examples/framework.rs | 2 +- wgpu/examples/mipmap/main.rs | 2 +- wgpu/examples/msaa-line/main.rs | 2 +- wgpu/examples/shadow/main.rs | 4 +-- wgpu/examples/skybox/main.rs | 4 +-- wgpu/examples/texture-arrays/main.rs | 10 +++--- wgpu/examples/water/main.rs | 4 +-- wgpu/src/backend/direct.rs | 32 +++++++++++++------ wgpu/src/lib.rs | 22 ++++++++++++- wgpu/src/util/device.rs | 14 ++++++-- wgpu/tests/clear_texture.rs | 2 +- wgpu/tests/queue_transfer.rs | 2 +- wgpu/tests/resource_error.rs | 2 +- wgpu/tests/shader_primitive_index/mod.rs | 2 +- wgpu/tests/texture_bounds.rs | 2 +- wgpu/tests/vertex_indices/mod.rs | 2 +- wgpu/tests/write_texture.rs | 2 +- wgpu/tests/zero_init_texture_after_discard.rs | 2 +- 28 files changed, 105 insertions(+), 65 deletions(-) diff --git a/deno_webgpu/src/texture.rs b/deno_webgpu/src/texture.rs index 5bc1d9d4f5..8a0a323609 100644 --- a/deno_webgpu/src/texture.rs +++ b/deno_webgpu/src/texture.rs @@ -56,7 +56,7 @@ pub fn op_webgpu_create_texture( dimension: args.dimension, format: args.format, usage: wgpu_types::TextureUsages::from_bits_truncate(args.usage), - view_formats: Some(args.view_formats), + view_formats: args.view_formats, }; gfx_put!(device => instance.device_create_texture( diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index df8a2d0618..c661f8f498 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -852,14 +852,12 @@ impl Device { )); } - if let Some(ref view_formats) = desc.view_formats { - for format in view_formats { - if desc.format == *format { - continue; - } - if desc.format.remove_srgb_suffix() != format.remove_srgb_suffix() { - return Err(CreateTextureError::InvalidViewFormat(*format, desc.format)); - } + for format in desc.view_formats.iter() { + if desc.format == *format { + continue; + } + if desc.format.remove_srgb_suffix() != format.remove_srgb_suffix() { + return Err(CreateTextureError::InvalidViewFormat(*format, desc.format)); } } @@ -1094,17 +1092,11 @@ impl Device { extent.depth_or_array_layers = view_layer_count; } let format = desc.format.unwrap_or(texture.desc.format); - if format != texture.desc.format { - let compatible = match texture.desc.view_formats { - Some(ref view_formats) => view_formats.contains(&format), - None => false, - }; - if !compatible { - return Err(resource::CreateTextureViewError::FormatReinterpretation { - texture: texture.desc.format, - view: format, - }); - } + if format != texture.desc.format && !texture.desc.view_formats.contains(&format) { + return Err(resource::CreateTextureViewError::FormatReinterpretation { + texture: texture.desc.format, + view: format, + }); } // filter the usages based on the other criteria diff --git a/wgpu-core/src/present.rs b/wgpu-core/src/present.rs index c1afb5e97c..7519dc5615 100644 --- a/wgpu-core/src/present.rs +++ b/wgpu-core/src/present.rs @@ -180,7 +180,7 @@ impl Global { format: config.format, dimension: wgt::TextureDimension::D2, usage: config.usage, - view_formats: None, + view_formats: vec![], }, hal_usage: conv::map_texture_usage(config.usage, config.format.into()), format_features: wgt::TextureFormatFeatures { diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index 00758d70b0..df51d70add 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -507,7 +507,7 @@ pub enum CreateTextureError { if *.2 { " due to downlevel restrictions" } else { "" } )] InvalidFormatUsages(wgt::TextureUsages, wgt::TextureFormat, bool), - #[error("The view format {0:?} is not compatible with texture format {1:?}.")] + #[error("The view format {0:?} is not compatible with texture format {1:?}, only changing srgb-ness is allowed.")] InvalidViewFormat(wgt::TextureFormat, wgt::TextureFormat), #[error("Texture usages {0:?} are not allowed on a texture of dimensions {1:?}")] InvalidDimensionUsages(wgt::TextureUsages, wgt::TextureDimension), diff --git a/wgpu-hal/src/gles/adapter.rs b/wgpu-hal/src/gles/adapter.rs index 833ae36d2d..cf19998806 100644 --- a/wgpu-hal/src/gles/adapter.rs +++ b/wgpu-hal/src/gles/adapter.rs @@ -283,7 +283,8 @@ impl super::Adapter { let mut downlevel_flags = wgt::DownlevelFlags::empty() | wgt::DownlevelFlags::NON_POWER_OF_TWO_MIPMAPPED_TEXTURES | wgt::DownlevelFlags::CUBE_ARRAY_TEXTURES - | wgt::DownlevelFlags::COMPARISON_SAMPLERS; + | wgt::DownlevelFlags::COMPARISON_SAMPLERS + | wgt::DownlevelFlags::VIEW_FORMATS; downlevel_flags.set(wgt::DownlevelFlags::COMPUTE_SHADERS, ver >= (3, 1)); downlevel_flags.set( wgt::DownlevelFlags::FRAGMENT_WRITABLE_STORAGE, diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index dd1ac41f8a..3328cbb45d 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -1139,6 +1139,11 @@ bitflags::bitflags! { /// /// Corresponds to Vulkan's `VkPhysicalDeviceFeatures.depthBiasClamp` const DEPTH_BIAS_CLAMP = 1 << 18; + + /// Supports specifying which view format values are allowed when create_view() is called on a texture. + /// + /// The WebGL and GLES backends doesn't support this. + const VIEW_FORMATS = 1 << 19; } } @@ -4360,9 +4365,7 @@ pub struct TextureDescriptor { /// Allowed usages of the texture. If used in other ways, the operation will panic. pub usage: TextureUsages, /// Specifies what view format values will be allowed when calling create_view() on this texture. - /// Note: Adding a format to this list may have a significant performance impact, - /// so it is best to avoid adding formats unnecessarily. - pub view_formats: Option>, + pub view_formats: Vec, } impl TextureDescriptor { @@ -4397,7 +4400,7 @@ impl TextureDescriptor { /// dimension: wgpu::TextureDimension::D3, /// format: wgpu::TextureFormat::Rgba8Sint, /// usage: wgpu::TextureUsages::empty(), - /// view_formats: None + /// view_formats: &[] /// }; /// /// assert_eq!(desc.mip_level_size(0), Some(wgpu::Extent3d { width: 100, height: 60, depth_or_array_layers: 1 })); diff --git a/wgpu/examples/bunnymark/main.rs b/wgpu/examples/bunnymark/main.rs index 871c45818f..4c82aa2041 100644 --- a/wgpu/examples/bunnymark/main.rs +++ b/wgpu/examples/bunnymark/main.rs @@ -152,7 +152,7 @@ impl framework::Example for Example { dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8UnormSrgb, usage: wgpu::TextureUsages::COPY_DST | wgpu::TextureUsages::TEXTURE_BINDING, - view_formats: None, + view_formats: &[], }); queue.write_texture( texture.as_image_copy(), diff --git a/wgpu/examples/capture/main.rs b/wgpu/examples/capture/main.rs index 46e90d1a0b..04a73f93ca 100644 --- a/wgpu/examples/capture/main.rs +++ b/wgpu/examples/capture/main.rs @@ -83,7 +83,7 @@ async fn create_red_image_with_dimensions( format: wgpu::TextureFormat::Rgba8UnormSrgb, usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC, label: None, - view_formats: None, + view_formats: &[], }); // Set the background to be red diff --git a/wgpu/examples/conservative-raster/main.rs b/wgpu/examples/conservative-raster/main.rs index fb1ea12a6d..b82feab2f6 100644 --- a/wgpu/examples/conservative-raster/main.rs +++ b/wgpu/examples/conservative-raster/main.rs @@ -36,7 +36,7 @@ impl Example { format: RENDER_TARGET_FORMAT, usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::RENDER_ATTACHMENT, - view_formats: None, + view_formats: &[], }) .create_view(&Default::default()); diff --git a/wgpu/examples/cube/main.rs b/wgpu/examples/cube/main.rs index d2c3315a68..3d646186f3 100644 --- a/wgpu/examples/cube/main.rs +++ b/wgpu/examples/cube/main.rs @@ -202,7 +202,7 @@ impl framework::Example for Example { dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::R8Uint, usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, - view_formats: None, + view_formats: &[], }); let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default()); queue.write_texture( diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index b0ae02a00a..797b3c9ecd 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -523,7 +523,7 @@ pub fn test(mut params: FrameworkRefTest) { dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8UnormSrgb, usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC, - view_formats: None, + view_formats: &[], }); let dst_view = dst_texture.create_view(&wgpu::TextureViewDescriptor::default()); diff --git a/wgpu/examples/mipmap/main.rs b/wgpu/examples/mipmap/main.rs index 9985fd8867..d5afa2e2f7 100644 --- a/wgpu/examples/mipmap/main.rs +++ b/wgpu/examples/mipmap/main.rs @@ -232,7 +232,7 @@ impl framework::Example for Example { | wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_DST, label: None, - view_formats: None, + view_formats: &[], }); let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default()); //Note: we could use queue.write_texture instead, and this is what other diff --git a/wgpu/examples/msaa-line/main.rs b/wgpu/examples/msaa-line/main.rs index 0a24c2be00..a5777d71f7 100644 --- a/wgpu/examples/msaa-line/main.rs +++ b/wgpu/examples/msaa-line/main.rs @@ -109,7 +109,7 @@ impl Example { format: config.format, usage: wgpu::TextureUsages::RENDER_ATTACHMENT, label: None, - view_formats: None, + view_formats: &[], }; device diff --git a/wgpu/examples/shadow/main.rs b/wgpu/examples/shadow/main.rs index c217d423ba..3b1f10d404 100644 --- a/wgpu/examples/shadow/main.rs +++ b/wgpu/examples/shadow/main.rs @@ -197,7 +197,7 @@ impl Example { format: Self::DEPTH_FORMAT, usage: wgpu::TextureUsages::RENDER_ATTACHMENT, label: None, - view_formats: None, + view_formats: &[], }); depth_texture.create_view(&wgpu::TextureViewDescriptor::default()) @@ -386,7 +386,7 @@ impl framework::Example for Example { format: Self::SHADOW_FORMAT, usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING, label: None, - view_formats: None, + view_formats: &[], }); let shadow_view = shadow_texture.create_view(&wgpu::TextureViewDescriptor::default()); diff --git a/wgpu/examples/skybox/main.rs b/wgpu/examples/skybox/main.rs index b9cfd9f0cb..5533cf77da 100644 --- a/wgpu/examples/skybox/main.rs +++ b/wgpu/examples/skybox/main.rs @@ -85,7 +85,7 @@ impl Skybox { format: Self::DEPTH_FORMAT, usage: wgpu::TextureUsages::RENDER_ATTACHMENT, label: None, - view_formats: None, + view_formats: &[], }); depth_texture.create_view(&wgpu::TextureViewDescriptor::default()) @@ -329,7 +329,7 @@ impl framework::Example for Skybox { format: skybox_format, usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, label: None, - view_formats: None, + view_formats: &[], }, &image.data, ); diff --git a/wgpu/examples/texture-arrays/main.rs b/wgpu/examples/texture-arrays/main.rs index 6717a7b4f1..20aec8137c 100644 --- a/wgpu/examples/texture-arrays/main.rs +++ b/wgpu/examples/texture-arrays/main.rs @@ -164,26 +164,26 @@ impl framework::Example for Example { format: wgpu::TextureFormat::Rgba8UnormSrgb, usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, label: None, - view_formats: None, + view_formats: &[], }; let red_texture = device.create_texture(&wgpu::TextureDescriptor { label: Some("red"), - view_formats: None, + view_formats: &[], ..texture_descriptor }); let green_texture = device.create_texture(&wgpu::TextureDescriptor { label: Some("green"), - view_formats: None, + view_formats: &[], ..texture_descriptor }); let blue_texture = device.create_texture(&wgpu::TextureDescriptor { label: Some("blue"), - view_formats: None, + view_formats: &[], ..texture_descriptor }); let white_texture = device.create_texture(&wgpu::TextureDescriptor { label: Some("white"), - view_formats: None, + view_formats: &[], ..texture_descriptor }); diff --git a/wgpu/examples/water/main.rs b/wgpu/examples/water/main.rs index 37f2e8d392..dfcd4ec1db 100644 --- a/wgpu/examples/water/main.rs +++ b/wgpu/examples/water/main.rs @@ -197,7 +197,7 @@ impl Example { usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST | wgpu::TextureUsages::RENDER_ATTACHMENT, - view_formats: None, + view_formats: &[], }); let draw_depth_buffer = device.create_texture(&wgpu::TextureDescriptor { @@ -210,7 +210,7 @@ impl Example { usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST | wgpu::TextureUsages::RENDER_ATTACHMENT, - view_formats: None, + view_formats: &[], }); let color_sampler = device.create_sampler(&wgpu::SamplerDescriptor { diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index 82613084b3..1221dcd878 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -135,15 +135,19 @@ impl Context { device: &Device, desc: &TextureDescriptor, ) -> Texture { - let global = &self.0; - let (id, error) = unsafe { - global.create_texture_from_hal::( - hal_texture, - device.id, - &desc.map_label(|l| l.map(Borrowed)), - (), - ) + let descriptor = wgt::TextureDescriptor { + label: desc.label.map(Borrowed), + size: desc.size, + mip_level_count: desc.mip_level_count, + sample_count: desc.sample_count, + format: desc.format, + dimension: desc.dimension, + usage: desc.usage, + view_formats: desc.view_formats.to_vec(), }; + let global = &self.0; + let (id, error) = + unsafe { global.create_texture_from_hal::(hal_texture, device.id, &descriptor, ()) }; if let Some(cause) = error { self.handle_error( &device.error_sink, @@ -1249,10 +1253,20 @@ impl crate::Context for Context { device_data: &Self::DeviceData, desc: &TextureDescriptor, ) -> (Self::TextureId, Self::TextureData) { + let wgt_desc = wgt::TextureDescriptor { + label: desc.label.map(Borrowed), + size: desc.size, + mip_level_count: desc.mip_level_count, + sample_count: desc.sample_count, + format: desc.format, + dimension: desc.dimension, + usage: desc.usage, + view_formats: desc.view_formats.to_vec(), + }; let global = &self.0; let (id, error) = wgc::gfx_select!(device => global.device_create_texture( *device, - &desc.map_label(|l| l.map(Borrowed)), + &wgt_desc, () )); if let Some(cause) = error { diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index b5a12cdb71..b8b7d8df6c 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -896,7 +896,27 @@ static_assertions::assert_impl_all!(RenderBundleDescriptor: Send, Sync); /// /// Corresponds to [WebGPU `GPUTextureDescriptor`]( /// https://gpuweb.github.io/gpuweb/#dictdef-gputexturedescriptor). -pub type TextureDescriptor<'a> = wgt::TextureDescriptor>; +#[derive(Clone, Debug)] +pub struct TextureDescriptor<'a> { + /// Debug label of the texture. This will show up in graphics debuggers for easy identification. + pub label: Label<'a>, + /// Size of the texture. All components must be greater than zero. For a + /// regular 1D/2D texture, the unused sizes will be 1. For 2DArray textures, + /// Z is the number of 2D textures in that array. + pub size: Extent3d, + /// Mip count of texture. For a texture with no extra mips, this must be 1. + pub mip_level_count: u32, + /// Sample count of texture. If this is not 1, texture must have [`BindingType::Texture::multisampled`] set to true. + pub sample_count: u32, + /// Dimensions of the texture. + pub dimension: TextureDimension, + /// Format of the texture. + pub format: TextureFormat, + /// Allowed usages of the texture. If used in other ways, the operation will panic. + pub usage: TextureUsages, + /// Specifies what view format values will be allowed when calling create_view() on this texture. + pub view_formats: &'a [TextureFormat], +} static_assertions::assert_impl_all!(TextureDescriptor: Send, Sync); /// Describes a [`QuerySet`]. /// diff --git a/wgpu/src/util/device.rs b/wgpu/src/util/device.rs index b441041a71..159692082a 100644 --- a/wgpu/src/util/device.rs +++ b/wgpu/src/util/device.rs @@ -82,18 +82,28 @@ impl DeviceExt for crate::Device { desc: &crate::TextureDescriptor, data: &[u8], ) -> crate::Texture { + let wgt_desc = wgt::TextureDescriptor { + label: Some(""), + size: desc.size, + mip_level_count: desc.mip_level_count, + sample_count: desc.sample_count, + format: desc.format, + dimension: desc.dimension, + usage: desc.usage, + view_formats: vec![], + }; // Implicitly add the COPY_DST usage let mut desc = desc.to_owned(); desc.usage |= crate::TextureUsages::COPY_DST; let texture = self.create_texture(&desc); let format_info = desc.format.describe(); - let layer_iterations = desc.array_layer_count(); + let layer_iterations = wgt_desc.array_layer_count(); let mut binary_offset = 0; for layer in 0..layer_iterations { for mip in 0..desc.mip_level_count { - let mut mip_size = desc.mip_level_size(mip).unwrap(); + let mut mip_size = wgt_desc.mip_level_size(mip).unwrap(); // copying layers separately if desc.dimension != wgt::TextureDimension::D3 { mip_size.depth_or_array_layers = 1; diff --git a/wgpu/tests/clear_texture.rs b/wgpu/tests/clear_texture.rs index 6de80cc428..556bd8d55d 100644 --- a/wgpu/tests/clear_texture.rs +++ b/wgpu/tests/clear_texture.rs @@ -225,7 +225,7 @@ fn single_texture_clear_test( // Forces internally the required usages to be able to clear it. // This is not visible on the API level. usage: wgpu::TextureUsages::TEXTURE_BINDING, - view_formats: None, + view_formats: &[], }); let mut encoder = ctx .device diff --git a/wgpu/tests/queue_transfer.rs b/wgpu/tests/queue_transfer.rs index 1ded69882b..3ab1cfa98e 100644 --- a/wgpu/tests/queue_transfer.rs +++ b/wgpu/tests/queue_transfer.rs @@ -21,7 +21,7 @@ fn queue_write_texture_overflow() { dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba32Float, usage: wgpu::TextureUsages::COPY_DST, - view_formats: None, + view_formats: &[], }); let data = vec![255; 128]; diff --git a/wgpu/tests/resource_error.rs b/wgpu/tests/resource_error.rs index 672cbd72a3..eb88779100 100644 --- a/wgpu/tests/resource_error.rs +++ b/wgpu/tests/resource_error.rs @@ -44,7 +44,7 @@ fn bad_texture() { dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8UnormSrgb, usage: wgpu::TextureUsages::all(), - view_formats: None, + view_formats: &[], }) }); diff --git a/wgpu/tests/shader_primitive_index/mod.rs b/wgpu/tests/shader_primitive_index/mod.rs index 08b348e3e5..086bc181d9 100644 --- a/wgpu/tests/shader_primitive_index/mod.rs +++ b/wgpu/tests/shader_primitive_index/mod.rs @@ -165,7 +165,7 @@ fn pulling_common( dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8Unorm, usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC, - view_formats: None, + view_formats: &[], }); let color_view = color_texture.create_view(&wgpu::TextureViewDescriptor::default()); diff --git a/wgpu/tests/texture_bounds.rs b/wgpu/tests/texture_bounds.rs index f302f066be..3bdb9f23e7 100644 --- a/wgpu/tests/texture_bounds.rs +++ b/wgpu/tests/texture_bounds.rs @@ -103,7 +103,7 @@ const TEXTURE_DESCRIPTOR: wgpu::TextureDescriptor = wgpu::TextureDescriptor { dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8UnormSrgb, usage: wgpu::TextureUsages::COPY_DST.union(wgpu::TextureUsages::COPY_SRC), - view_formats: None, + view_formats: &[], }; const BYTES_PER_PIXEL: u32 = 4; diff --git a/wgpu/tests/vertex_indices/mod.rs b/wgpu/tests/vertex_indices/mod.rs index 706d780cdb..055e10a40b 100644 --- a/wgpu/tests/vertex_indices/mod.rs +++ b/wgpu/tests/vertex_indices/mod.rs @@ -97,7 +97,7 @@ fn pulling_common( dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8Unorm, usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_DST, - view_formats: None, + view_formats: &[], }, &[0, 0, 0, 1], ) diff --git a/wgpu/tests/write_texture.rs b/wgpu/tests/write_texture.rs index face573e1f..7e757606ea 100644 --- a/wgpu/tests/write_texture.rs +++ b/wgpu/tests/write_texture.rs @@ -25,7 +25,7 @@ fn write_texture_subset() { | wgpu::TextureUsages::TEXTURE_BINDING, mip_level_count: 1, sample_count: 1, - view_formats: None, + view_formats: &[], }); let data = vec![1u8; size as usize * 2]; // Write the first two rows diff --git a/wgpu/tests/zero_init_texture_after_discard.rs b/wgpu/tests/zero_init_texture_after_discard.rs index 0672c21176..6a9bc0a99c 100644 --- a/wgpu/tests/zero_init_texture_after_discard.rs +++ b/wgpu/tests/zero_init_texture_after_discard.rs @@ -208,7 +208,7 @@ fn create_white_texture_and_readback_buffer( | wgpu::TextureUsages::COPY_SRC | wgpu::TextureUsages::RENDER_ATTACHMENT }, - view_formats: None, + view_formats: &[], }); // Clear using a write_texture operation. We could also clear using a render_pass clear. From 22868ccf8cd05ae451129defc4c933f34a54363c Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Mon, 28 Nov 2022 09:14:25 +0800 Subject: [PATCH 06/20] Set `view_formats` on web target --- wgpu/src/backend/web.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wgpu/src/backend/web.rs b/wgpu/src/backend/web.rs index 9a3725d4c4..3014950aa5 100644 --- a/wgpu/src/backend/web.rs +++ b/wgpu/src/backend/web.rs @@ -1546,6 +1546,12 @@ impl crate::context::Context for Context { mapped_desc.dimension(map_texture_dimension(desc.dimension)); mapped_desc.mip_level_count(desc.mip_level_count); mapped_desc.sample_count(desc.sample_count); + let mapped_view_formats = desc + .view_formats + .iter() + .map(|format| JsValue::from(map_texture_format(*format))) + .collect::(); + mapped_desc.view_formats(&mapped_view_formats); (create_identified(device.0.create_texture(&mapped_desc)), ()) } From ecfd9715f42c7f4969473422a7addb530d8cf57b Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Mon, 28 Nov 2022 22:43:47 +0800 Subject: [PATCH 07/20] Add a `reinterpret_srgb_ness` test --- wgpu-types/src/lib.rs | 1 + wgpu/src/lib.rs | 1 + wgpu/tests/common/image.rs | 2 +- wgpu/tests/root.rs | 1 + wgpu/tests/shader_view_format/mod.rs | 201 ++++++++++++++++++ .../tests/shader_view_format/view_format.wgsl | 12 ++ 6 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 wgpu/tests/shader_view_format/mod.rs create mode 100644 wgpu/tests/shader_view_format/view_format.wgsl diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 3328cbb45d..c196130331 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -4365,6 +4365,7 @@ pub struct TextureDescriptor { /// Allowed usages of the texture. If used in other ways, the operation will panic. pub usage: TextureUsages, /// Specifies what view format values will be allowed when calling create_view() on this texture. + /// Note: currenly, only srgb-ness is allowed. pub view_formats: Vec, } diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index b8b7d8df6c..46b2fcffbb 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -915,6 +915,7 @@ pub struct TextureDescriptor<'a> { /// Allowed usages of the texture. If used in other ways, the operation will panic. pub usage: TextureUsages, /// Specifies what view format values will be allowed when calling create_view() on this texture. + /// Note: currenly, only srgb-ness is allowed. pub view_formats: &'a [TextureFormat], } static_assertions::assert_impl_all!(TextureDescriptor: Send, Sync); diff --git a/wgpu/tests/common/image.rs b/wgpu/tests/common/image.rs index fc80ac8eac..8911d9a0e7 100644 --- a/wgpu/tests/common/image.rs +++ b/wgpu/tests/common/image.rs @@ -64,7 +64,7 @@ fn write_png( } } -fn calc_difference(lhs: u8, rhs: u8) -> u8 { +pub fn calc_difference(lhs: u8, rhs: u8) -> u8 { (lhs as i16 - rhs as i16).unsigned_abs() as u8 } diff --git a/wgpu/tests/root.rs b/wgpu/tests/root.rs index a3132eda81..122bf790a7 100644 --- a/wgpu/tests/root.rs +++ b/wgpu/tests/root.rs @@ -17,6 +17,7 @@ mod resource_descriptor_accessor; mod resource_error; mod shader; mod shader_primitive_index; +mod shader_view_format; mod texture_bounds; mod transfer; mod vertex_indices; diff --git a/wgpu/tests/shader_view_format/mod.rs b/wgpu/tests/shader_view_format/mod.rs new file mode 100644 index 0000000000..1fa274b633 --- /dev/null +++ b/wgpu/tests/shader_view_format/mod.rs @@ -0,0 +1,201 @@ +use crate::common::{image::calc_difference, initialize_test, TestParameters, TestingContext}; +use std::num::NonZeroU32; +use wgpu::{util::DeviceExt, TextureFormat}; + +#[test] +fn reinterpret_srgb_ness() { + let parameters = TestParameters::default(); + initialize_test(parameters, |ctx| { + let shader = ctx + .device + .create_shader_module(wgpu::include_wgsl!("view_format.wgsl")); + + let size = wgpu::Extent3d { + width: 2, + height: 2, + depth_or_array_layers: 1, + }; + let unorm_data: [[u8; 4]; 4] = [ + [180, 0, 0, 255], + [0, 84, 0, 127], + [0, 0, 62, 100], + [62, 180, 84, 90], + ]; + let srgb_data: [[u8; 4]; 4] = [ + [116, 0, 0, 255], + [0, 23, 0, 127], + [0, 0, 12, 100], + [12, 116, 23, 90], + ]; + + // Reinterpret Rgba8Unorm as Rgba8UnormSrgb + reinterpret( + &ctx, + &shader, + size, + TextureFormat::Rgba8Unorm, + TextureFormat::Rgba8UnormSrgb, + &unorm_data, + &srgb_data, + ); + + // Reinterpret Rgba8UnormSrgb back to Rgba8Unorm + reinterpret( + &ctx, + &shader, + size, + TextureFormat::Rgba8UnormSrgb, + TextureFormat::Rgba8Unorm, + &srgb_data, + &unorm_data, + ); + }); +} + +fn reinterpret( + ctx: &TestingContext, + shader: &wgpu::ShaderModule, + size: wgpu::Extent3d, + src_format: wgpu::TextureFormat, + reinterpret_to: wgpu::TextureFormat, + src_data: &[[u8; 4]], + expect_data: &[[u8; 4]], +) { + let tex = ctx.device.create_texture_with_data( + &ctx.queue, + &wgpu::TextureDescriptor { + label: None, + dimension: wgpu::TextureDimension::D2, + size, + format: src_format, + usage: wgpu::TextureUsages::COPY_DST | wgpu::TextureUsages::TEXTURE_BINDING, + mip_level_count: 1, + sample_count: 1, + view_formats: &[reinterpret_to], + }, + bytemuck::cast_slice(src_data), + ); + let tv = tex.create_view(&wgpu::TextureViewDescriptor { + format: Some(reinterpret_to), + ..Default::default() + }); + let pipeline = ctx + .device + .create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("reinterpret pipeline"), + layout: None, + vertex: wgpu::VertexState { + module: shader, + entry_point: "vs_main", + buffers: &[], + }, + fragment: Some(wgpu::FragmentState { + module: shader, + entry_point: "fs_main", + targets: &[Some(src_format.into())], + }), + primitive: wgpu::PrimitiveState { + front_face: wgpu::FrontFace::Cw, + ..Default::default() + }, + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + multiview: None, + }); + let bind_group = ctx.device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &pipeline.get_bind_group_layout(0), + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&tv), + }], + label: None, + }); + + let out_tex = ctx.device.create_texture(&wgpu::TextureDescriptor { + label: None, + size, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: src_format, + usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC, + view_formats: &[], + }); + let target_view = out_tex.create_view(&wgpu::TextureViewDescriptor::default()); + + let mut encoder = ctx + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor::default()); + let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + ops: wgpu::Operations::default(), + resolve_target: None, + view: &target_view, + })], + depth_stencil_attachment: None, + label: None, + }); + rpass.set_pipeline(&pipeline); + rpass.set_bind_group(0, &bind_group, &[]); + rpass.draw(0..3, 0..1); + drop(rpass); + ctx.queue.submit(Some(encoder.finish())); + + let read_buffer = ctx.device.create_buffer(&wgpu::BufferDescriptor { + label: None, + size: wgpu::COPY_BYTES_PER_ROW_ALIGNMENT as u64 * 2, + usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); + + let mut encoder = ctx + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); + encoder.copy_texture_to_buffer( + wgpu::ImageCopyTexture { + texture: &out_tex, + mip_level: 0, + origin: wgpu::Origin3d::ZERO, + aspect: wgpu::TextureAspect::All, + }, + wgpu::ImageCopyBuffer { + buffer: &read_buffer, + layout: wgpu::ImageDataLayout { + offset: 0, + bytes_per_row: NonZeroU32::new(wgpu::COPY_BYTES_PER_ROW_ALIGNMENT), + rows_per_image: None, + }, + }, + size, + ); + ctx.queue.submit(Some(encoder.finish())); + + let slice = read_buffer.slice(..); + slice.map_async(wgpu::MapMode::Read, |_| ()); + ctx.device.poll(wgpu::Maintain::Wait); + + let data: Vec = slice.get_mapped_range().to_vec(); + for h in 0..size.height { + let offset = h * wgpu::COPY_BYTES_PER_ROW_ALIGNMENT; + for w in 0..size.width { + let expect = expect_data[(h * size.width + w) as usize]; + let index = (w * 4 + offset) as usize; + if calc_difference(expect[0], data[index]) > 1 + || calc_difference(expect[1], data[index + 1]) > 1 + || calc_difference(expect[2], data[index + 2]) > 1 + || calc_difference(expect[3], data[index + 3]) > 0 + { + panic!( + "Reinterpret {:?} as {:?} mismatch! expect {:?} get [{}, {}, {}, {}]", + src_format, + reinterpret_to, + expect, + data[index], + data[index + 1], + data[index + 2], + data[index + 3] + ) + } + } + } +} diff --git a/wgpu/tests/shader_view_format/view_format.wgsl b/wgpu/tests/shader_view_format/view_format.wgsl new file mode 100644 index 0000000000..98d60460a6 --- /dev/null +++ b/wgpu/tests/shader_view_format/view_format.wgsl @@ -0,0 +1,12 @@ +@vertex +fn vs_main(@builtin(vertex_index) vertexIndex: u32) -> @builtin(position) vec4 { + let uv: vec2 = vec2(f32((vertexIndex << 1u) & 2u), f32(vertexIndex & 2u)); + return vec4(uv * 2.0 - 1.0, 0.0, 1.0); +} + +@group(0) @binding(0) var tex: texture_2d; + +@fragment +fn fs_main(@builtin(position) coord: vec4) -> @location(0) vec4 { + return textureLoad(tex, vec2(coord.xy), 0); +} \ No newline at end of file From 11329c23eaf1a76eea80df3756b4d57debb49d88 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Tue, 29 Nov 2022 11:44:42 +0800 Subject: [PATCH 08/20] Define tolerance data to improve test --- player/tests/data/clear-buffer-texture.ron | 1 + player/tests/data/quad.ron | 1 + .../tests/data/zero-init-texture-binding.ron | 2 ++ .../data/zero-init-texture-copytobuffer.ron | 1 + .../data/zero-init-texture-rendertarget.ron | 1 + wgpu/tests/shader_view_format/mod.rs | 36 ++++++++++--------- 6 files changed, 26 insertions(+), 16 deletions(-) diff --git a/player/tests/data/clear-buffer-texture.ron b/player/tests/data/clear-buffer-texture.ron index 7d32a688e7..c6879e31da 100644 --- a/player/tests/data/clear-buffer-texture.ron +++ b/player/tests/data/clear-buffer-texture.ron @@ -31,6 +31,7 @@ dimension: r#2d, format: "rgba8unorm", usage: 27, + view_formats: [], )), // First fill the texture to ensure it wasn't just zero initialized or "happened" to be zero. WriteTexture( diff --git a/player/tests/data/quad.ron b/player/tests/data/quad.ron index 1f7cb266f4..563ba24b84 100644 --- a/player/tests/data/quad.ron +++ b/player/tests/data/quad.ron @@ -28,6 +28,7 @@ dimension: r#2d, format: "rgba8unorm", usage: 27, + view_formats: [], )), CreateTextureView( id: Id(0, 1, Empty), diff --git a/player/tests/data/zero-init-texture-binding.ron b/player/tests/data/zero-init-texture-binding.ron index c6f8c40a53..e94255cfc3 100644 --- a/player/tests/data/zero-init-texture-binding.ron +++ b/player/tests/data/zero-init-texture-binding.ron @@ -28,6 +28,7 @@ dimension: r#2d, format: "rgba8unorm", usage: 5, // SAMPLED + COPY_SRC + view_formats: [], )), CreateTextureView( id: Id(0, 1, Empty), @@ -54,6 +55,7 @@ dimension: r#2d, format: "rgba8unorm", usage: 9, // STORAGE + COPY_SRC + view_formats: [], )), CreateTextureView( id: Id(1, 1, Empty), diff --git a/player/tests/data/zero-init-texture-copytobuffer.ron b/player/tests/data/zero-init-texture-copytobuffer.ron index e3f72f1a08..0bb16ccebb 100644 --- a/player/tests/data/zero-init-texture-copytobuffer.ron +++ b/player/tests/data/zero-init-texture-copytobuffer.ron @@ -21,6 +21,7 @@ dimension: r#2d, format: "rgba8unorm", usage: 1, // COPY_SRC + view_formats: [], )), CreateBuffer( Id(0, 1, Empty), diff --git a/player/tests/data/zero-init-texture-rendertarget.ron b/player/tests/data/zero-init-texture-rendertarget.ron index 5741c7c33c..831af942a2 100644 --- a/player/tests/data/zero-init-texture-rendertarget.ron +++ b/player/tests/data/zero-init-texture-rendertarget.ron @@ -21,6 +21,7 @@ dimension: r#2d, format: "rgba8unorm", usage: 17, // RENDER_ATTACHMENT + COPY_SRC + view_formats: [], )), CreateTextureView( id: Id(0, 1, Empty), diff --git a/wgpu/tests/shader_view_format/mod.rs b/wgpu/tests/shader_view_format/mod.rs index 1fa274b633..49df0b5df7 100644 --- a/wgpu/tests/shader_view_format/mod.rs +++ b/wgpu/tests/shader_view_format/mod.rs @@ -6,15 +6,6 @@ use wgpu::{util::DeviceExt, TextureFormat}; fn reinterpret_srgb_ness() { let parameters = TestParameters::default(); initialize_test(parameters, |ctx| { - let shader = ctx - .device - .create_shader_module(wgpu::include_wgsl!("view_format.wgsl")); - - let size = wgpu::Extent3d { - width: 2, - height: 2, - depth_or_array_layers: 1, - }; let unorm_data: [[u8; 4]; 4] = [ [180, 0, 0, 255], [0, 84, 0, 127], @@ -28,6 +19,16 @@ fn reinterpret_srgb_ness() { [12, 116, 23, 90], ]; + let size = wgpu::Extent3d { + width: 2, + height: 2, + depth_or_array_layers: 1, + }; + + let shader = ctx + .device + .create_shader_module(wgpu::include_wgsl!("view_format.wgsl")); + // Reinterpret Rgba8Unorm as Rgba8UnormSrgb reinterpret( &ctx, @@ -111,7 +112,7 @@ fn reinterpret( label: None, }); - let out_tex = ctx.device.create_texture(&wgpu::TextureDescriptor { + let target_tex = ctx.device.create_texture(&wgpu::TextureDescriptor { label: None, size, mip_level_count: 1, @@ -121,7 +122,7 @@ fn reinterpret( usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC, view_formats: &[], }); - let target_view = out_tex.create_view(&wgpu::TextureViewDescriptor::default()); + let target_view = target_tex.create_view(&wgpu::TextureViewDescriptor::default()); let mut encoder = ctx .device @@ -153,7 +154,7 @@ fn reinterpret( .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); encoder.copy_texture_to_buffer( wgpu::ImageCopyTexture { - texture: &out_tex, + texture: &target_tex, mip_level: 0, origin: wgpu::Origin3d::ZERO, aspect: wgpu::TextureAspect::All, @@ -175,15 +176,18 @@ fn reinterpret( ctx.device.poll(wgpu::Maintain::Wait); let data: Vec = slice.get_mapped_range().to_vec(); + let tolerance_data: [[u8; 4]; 4] = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [1, 1, 1, 0]]; + for h in 0..size.height { let offset = h * wgpu::COPY_BYTES_PER_ROW_ALIGNMENT; for w in 0..size.width { let expect = expect_data[(h * size.width + w) as usize]; + let tolerance = tolerance_data[(h * size.width + w) as usize]; let index = (w * 4 + offset) as usize; - if calc_difference(expect[0], data[index]) > 1 - || calc_difference(expect[1], data[index + 1]) > 1 - || calc_difference(expect[2], data[index + 2]) > 1 - || calc_difference(expect[3], data[index + 3]) > 0 + if calc_difference(expect[0], data[index]) > tolerance[0] + || calc_difference(expect[1], data[index + 1]) > tolerance[1] + || calc_difference(expect[2], data[index + 2]) > tolerance[2] + || calc_difference(expect[3], data[index + 3]) > tolerance[3] { panic!( "Reinterpret {:?} as {:?} mismatch! expect {:?} get [{}, {}, {}, {}]", From 0775f292d6746f14cd36757968c5ee21ac2d60e3 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Tue, 29 Nov 2022 14:24:46 +0800 Subject: [PATCH 09/20] Set `VIEW_FORMATS` downlevel_flag for test --- wgpu-core/src/device/mod.rs | 14 +++++++++----- wgpu-core/src/resource.rs | 2 ++ wgpu/tests/shader_view_format/mod.rs | 7 +++++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index c661f8f498..83ec81c9c4 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -1092,11 +1092,15 @@ impl Device { extent.depth_or_array_layers = view_layer_count; } let format = desc.format.unwrap_or(texture.desc.format); - if format != texture.desc.format && !texture.desc.view_formats.contains(&format) { - return Err(resource::CreateTextureViewError::FormatReinterpretation { - texture: texture.desc.format, - view: format, - }); + if format != texture.desc.format { + if texture.desc.view_formats.contains(&format) { + self.require_downlevel_flags(wgt::DownlevelFlags::VIEW_FORMATS)?; + } else { + return Err(resource::CreateTextureViewError::FormatReinterpretation { + texture: texture.desc.format, + view: format, + }); + } } // filter the usages based on the other criteria diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index df51d70add..a4ce611aea 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -628,6 +628,8 @@ pub enum CreateTextureViewError { texture: wgt::TextureFormat, view: wgt::TextureFormat, }, + #[error(transparent)] + MissingDownlevelFlags(#[from] MissingDownlevelFlags), } #[derive(Clone, Debug, Error)] diff --git a/wgpu/tests/shader_view_format/mod.rs b/wgpu/tests/shader_view_format/mod.rs index 49df0b5df7..f82f8851cf 100644 --- a/wgpu/tests/shader_view_format/mod.rs +++ b/wgpu/tests/shader_view_format/mod.rs @@ -1,10 +1,13 @@ use crate::common::{image::calc_difference, initialize_test, TestParameters, TestingContext}; use std::num::NonZeroU32; -use wgpu::{util::DeviceExt, TextureFormat}; +use wgpu::{util::DeviceExt, DownlevelFlags, Limits, TextureFormat}; #[test] fn reinterpret_srgb_ness() { - let parameters = TestParameters::default(); + let parameters = TestParameters::default() + .downlevel_flags(DownlevelFlags::VIEW_FORMATS) + .limits(Limits::downlevel_defaults()) + .specific_failure(Some(wgpu::Backends::GL), None, None, true); initialize_test(parameters, |ctx| { let unorm_data: [[u8; 4]; 4] = [ [180, 0, 0, 255], From c64a03fd2aea5b72697293b684c06752f594315c Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Wed, 7 Dec 2022 20:06:29 +0800 Subject: [PATCH 10/20] Add the missing field `view_formats` in `copy_overflow_z` test --- wgpu/tests/transfer.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wgpu/tests/transfer.rs b/wgpu/tests/transfer.rs index 1e94a31ff1..97d53149c0 100644 --- a/wgpu/tests/transfer.rs +++ b/wgpu/tests/transfer.rs @@ -21,6 +21,7 @@ fn copy_overflow_z() { usage: wgpu::TextureUsages::COPY_DST, mip_level_count: 1, sample_count: 1, + view_formats: &[], }); let t2 = ctx.device.create_texture(&wgpu::TextureDescriptor { label: None, @@ -34,6 +35,7 @@ fn copy_overflow_z() { usage: wgpu::TextureUsages::COPY_DST, mip_level_count: 1, sample_count: 1, + view_formats: &[], }); fail(&ctx.device, || { From fe57a2644b8808d91786e01b0e81475c62479a1b Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Wed, 7 Dec 2022 20:07:05 +0800 Subject: [PATCH 11/20] Update CHANGELOG --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90f7335877..e7080812e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -107,6 +107,18 @@ Additionally `Surface::get_default_config` now returns an Option and returns Non `wgpu`'s DX12 backend can now suballocate buffers and textures when the `windows_rs` feature is enabled, which can give a significant increase in performance (in testing I've seen a 10000%+ improvement in a simple scene with 200 `write_buffer` calls per frame, and a 40%+ improvement in [Bistro using Bevy](https://github.com/vleue/bevy_bistro_playground)). Previously `wgpu-hal`'s DX12 backend created a new heap on the GPU every time you called write_buffer (by calling `CreateCommittedResource`), whereas now with the `windows_rs` feature enabled it uses [`gpu_allocator`](https://crates.io/crates/gpu-allocator) to manage GPU memory (and calls `CreatePlacedResource` with a suballocated heap). By @Elabajaba in [#3163](https://github.com/gfx-rs/wgpu/pull/3163) +#### Texture Format Reinterpretation + +The `view_formats` field is used to specify formats that are compatible with the texture format to allow the creation of views with different formats, currently, only changing srgb-ness is allowed. + +```diff +let texture = device.create_texture(&wgpu::TextureDescriptor { + // ... + format: TextureFormat::Rgba8UnormSrgb, ++ view_formats: &[TextureFormat::Rgba8Unorm], +}); +``` + ### Changes #### General @@ -125,6 +137,7 @@ Additionally `Surface::get_default_config` now returns an Option and returns Non - Make `ObjectId` structure and invariants idiomatic. By @teoxoy in [#3347](https://github.com/gfx-rs/wgpu/pull/3347) - Add validation in accordance with WebGPU `GPUSamplerDescriptor` valid usage for `lodMinClamp` and `lodMaxClamp`. By @James2022-rgb in [#3353](https://github.com/gfx-rs/wgpu/pull/3353) - Remove panics in `Deref` implementations for `QueueWriteBufferView` and `BufferViewMut`. Instead, warnings are logged, since reading from these types is not recommended. By @botahamec in [#3336] +- Implement `view_formats` in TextureDescriptor to match the WebGPU spec. By @jinleili in [#3237](https://github.com/gfx-rs/wgpu/pull/3237) #### WebGPU From 3d62698dd2651271df0426beae279243e3f42d63 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Wed, 11 Jan 2023 13:24:46 +0800 Subject: [PATCH 12/20] Update wgpu-core/src/device/mod.rs Co-authored-by: Connor Fitzgerald --- wgpu-core/src/device/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 83ec81c9c4..d3ed405273 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -1093,14 +1093,13 @@ impl Device { } let format = desc.format.unwrap_or(texture.desc.format); if format != texture.desc.format { - if texture.desc.view_formats.contains(&format) { - self.require_downlevel_flags(wgt::DownlevelFlags::VIEW_FORMATS)?; - } else { + if !texture.desc.view_formats.contains(&format) { return Err(resource::CreateTextureViewError::FormatReinterpretation { texture: texture.desc.format, view: format, }); } + self.require_downlevel_flags(wgt::DownlevelFlags::VIEW_FORMATS)?; } // filter the usages based on the other criteria From b8d2178504ee238853b6541d66611899c3c23990 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Wed, 11 Jan 2023 16:49:10 +0800 Subject: [PATCH 13/20] rebase upstream/master --- wgpu-types/src/lib.rs | 2 +- wgpu/examples/stencil-triangles/main.rs | 1 + wgpu/src/lib.rs | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index c196130331..04f02dc9d5 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -4401,7 +4401,7 @@ impl TextureDescriptor { /// dimension: wgpu::TextureDimension::D3, /// format: wgpu::TextureFormat::Rgba8Sint, /// usage: wgpu::TextureUsages::empty(), - /// view_formats: &[] + /// view_formats: vec![] /// }; /// /// assert_eq!(desc.mip_level_size(0), Some(wgpu::Extent3d { width: 100, height: 60, depth_or_array_layers: 1 })); diff --git a/wgpu/examples/stencil-triangles/main.rs b/wgpu/examples/stencil-triangles/main.rs index 1de2ae8eb9..87c8ae143a 100644 --- a/wgpu/examples/stencil-triangles/main.rs +++ b/wgpu/examples/stencil-triangles/main.rs @@ -153,6 +153,7 @@ impl framework::Example for Triangles { sample_count: 1, dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Stencil8, + view_formats: &[], usage: wgpu::TextureUsages::RENDER_ATTACHMENT, }); diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 46b2fcffbb..f706c14974 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -2075,6 +2075,7 @@ impl Device { owned: true, descriptor: TextureDescriptor { label: None, + view_formats: &[], ..desc.clone() }, } @@ -2111,6 +2112,7 @@ impl Device { owned: true, descriptor: TextureDescriptor { label: None, + view_formats: &[], ..desc.clone() }, } @@ -4115,6 +4117,7 @@ impl Surface { mip_level_count: 1, sample_count: 1, dimension: TextureDimension::D2, + view_formats: &[], }; texture_id From 20784686fc8fe862b1b631de394bbc3787610415 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Thu, 12 Jan 2023 12:06:31 +0800 Subject: [PATCH 14/20] Remove duplicate definitions of TextureDescriptor --- wgpu-core/src/command/clear.rs | 2 +- wgpu-core/src/command/transfer.rs | 2 +- wgpu-core/src/init_tracker/texture.rs | 2 +- wgpu-core/src/resource.rs | 4 ++-- wgpu-types/src/lib.rs | 12 ++++++------ wgpu/src/lib.rs | 23 +---------------------- wgpu/src/util/device.rs | 21 +++++++++++---------- 7 files changed, 23 insertions(+), 43 deletions(-) diff --git a/wgpu-core/src/command/clear.rs b/wgpu-core/src/command/clear.rs index aa9d60638e..b3f436482b 100644 --- a/wgpu-core/src/command/clear.rs +++ b/wgpu-core/src/command/clear.rs @@ -308,7 +308,7 @@ pub(crate) fn clear_texture( } fn clear_texture_via_buffer_copies( - texture_desc: &wgt::TextureDescriptor<()>, + texture_desc: &wgt::TextureDescriptor<(), Vec>, alignments: &hal::Alignments, zero_buffer: &A::Buffer, // Buffer of size device::ZERO_BUFFER_SIZE range: TextureInitRange, diff --git a/wgpu-core/src/command/transfer.rs b/wgpu-core/src/command/transfer.rs index 70c01a9c46..073872f264 100644 --- a/wgpu-core/src/command/transfer.rs +++ b/wgpu-core/src/command/transfer.rs @@ -313,7 +313,7 @@ pub(crate) fn validate_linear_texture_data( /// [vtcr]: https://gpuweb.github.io/gpuweb/#valid-texture-copy-range pub(crate) fn validate_texture_copy_range( texture_copy_view: &ImageCopyTexture, - desc: &wgt::TextureDescriptor<()>, + desc: &wgt::TextureDescriptor<(), Vec>, texture_side: CopySide, copy_size: &Extent3d, ) -> Result<(hal::CopyExtent, u32), TransferError> { diff --git a/wgpu-core/src/init_tracker/texture.rs b/wgpu-core/src/init_tracker/texture.rs index 90167e6fa6..17368e1014 100644 --- a/wgpu-core/src/init_tracker/texture.rs +++ b/wgpu-core/src/init_tracker/texture.rs @@ -16,7 +16,7 @@ pub(crate) struct TextureInitRange { pub(crate) fn has_copy_partial_init_tracker_coverage( copy_size: &wgt::Extent3d, mip_level: u32, - desc: &wgt::TextureDescriptor<()>, + desc: &wgt::TextureDescriptor<(), Vec>, ) -> bool { let target_size = desc.mip_level_size(mip_level).unwrap(); copy_size.width != target_size.width diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index a4ce611aea..8d8433107c 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -297,7 +297,7 @@ impl Resource for StagingBuffer { } } -pub type TextureDescriptor<'a> = wgt::TextureDescriptor>; +pub type TextureDescriptor<'a> = wgt::TextureDescriptor, Vec>; #[derive(Debug)] pub(crate) enum TextureInner { @@ -338,7 +338,7 @@ pub enum TextureClearMode { pub struct Texture { pub(crate) inner: TextureInner, pub(crate) device_id: Stored, - pub(crate) desc: wgt::TextureDescriptor<()>, + pub(crate) desc: wgt::TextureDescriptor<(), Vec>, pub(crate) hal_usage: hal::TextureUses, pub(crate) format_features: wgt::TextureFormatFeatures, pub(crate) initialization_status: TextureInitTracker, diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 04f02dc9d5..70f6fc616e 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -4347,7 +4347,7 @@ fn test_max_mips() { #[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "trace", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -pub struct TextureDescriptor { +pub struct TextureDescriptor { /// Debug label of the texture. This will show up in graphics debuggers for easy identification. pub label: L, /// Size of the texture. All components must be greater than zero. For a @@ -4366,12 +4366,12 @@ pub struct TextureDescriptor { pub usage: TextureUsages, /// Specifies what view format values will be allowed when calling create_view() on this texture. /// Note: currenly, only srgb-ness is allowed. - pub view_formats: Vec, + pub view_formats: V, } -impl TextureDescriptor { +impl TextureDescriptor { /// Takes a closure and maps the label of the texture descriptor into another. - pub fn map_label(&self, fun: impl FnOnce(&L) -> K) -> TextureDescriptor { + pub fn map_label(&self, fun: impl FnOnce(&L) -> K) -> TextureDescriptor { TextureDescriptor { label: fun(&self.label), size: self.size, @@ -5119,7 +5119,7 @@ impl ImageSubresourceRange { } /// Returns the mip level range of a subresource range describes for a specific texture. - pub fn mip_range(&self, texture_desc: &TextureDescriptor) -> Range { + pub fn mip_range(&self, texture_desc: &TextureDescriptor) -> Range { self.base_mip_level..match self.mip_level_count { Some(mip_level_count) => self.base_mip_level + mip_level_count.get(), None => texture_desc.mip_level_count, @@ -5127,7 +5127,7 @@ impl ImageSubresourceRange { } /// Returns the layer range of a subresource range describes for a specific texture. - pub fn layer_range(&self, texture_desc: &TextureDescriptor) -> Range { + pub fn layer_range(&self, texture_desc: &TextureDescriptor) -> Range { self.base_array_layer..match self.array_layer_count { Some(array_layer_count) => self.base_array_layer + array_layer_count.get(), None => { diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index f706c14974..4fe3dcdf38 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -896,28 +896,7 @@ static_assertions::assert_impl_all!(RenderBundleDescriptor: Send, Sync); /// /// Corresponds to [WebGPU `GPUTextureDescriptor`]( /// https://gpuweb.github.io/gpuweb/#dictdef-gputexturedescriptor). -#[derive(Clone, Debug)] -pub struct TextureDescriptor<'a> { - /// Debug label of the texture. This will show up in graphics debuggers for easy identification. - pub label: Label<'a>, - /// Size of the texture. All components must be greater than zero. For a - /// regular 1D/2D texture, the unused sizes will be 1. For 2DArray textures, - /// Z is the number of 2D textures in that array. - pub size: Extent3d, - /// Mip count of texture. For a texture with no extra mips, this must be 1. - pub mip_level_count: u32, - /// Sample count of texture. If this is not 1, texture must have [`BindingType::Texture::multisampled`] set to true. - pub sample_count: u32, - /// Dimensions of the texture. - pub dimension: TextureDimension, - /// Format of the texture. - pub format: TextureFormat, - /// Allowed usages of the texture. If used in other ways, the operation will panic. - pub usage: TextureUsages, - /// Specifies what view format values will be allowed when calling create_view() on this texture. - /// Note: currenly, only srgb-ness is allowed. - pub view_formats: &'a [TextureFormat], -} +pub type TextureDescriptor<'a> = wgt::TextureDescriptor, &'a [TextureFormat]>; static_assertions::assert_impl_all!(TextureDescriptor: Send, Sync); /// Describes a [`QuerySet`]. /// diff --git a/wgpu/src/util/device.rs b/wgpu/src/util/device.rs index 159692082a..cb801d9d81 100644 --- a/wgpu/src/util/device.rs +++ b/wgpu/src/util/device.rs @@ -82,16 +82,17 @@ impl DeviceExt for crate::Device { desc: &crate::TextureDescriptor, data: &[u8], ) -> crate::Texture { - let wgt_desc = wgt::TextureDescriptor { - label: Some(""), - size: desc.size, - mip_level_count: desc.mip_level_count, - sample_count: desc.sample_count, - format: desc.format, - dimension: desc.dimension, - usage: desc.usage, - view_formats: vec![], - }; + let wgt_desc: wgt::TextureDescriptor, Vec> = + wgt::TextureDescriptor { + label: Some(""), + size: desc.size, + mip_level_count: desc.mip_level_count, + sample_count: desc.sample_count, + format: desc.format, + dimension: desc.dimension, + usage: desc.usage, + view_formats: desc.view_formats.to_vec(), + }; // Implicitly add the COPY_DST usage let mut desc = desc.to_owned(); desc.usage |= crate::TextureUsages::COPY_DST; From bac83f6a220060cd224f0b68e0b7f129501efeb9 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Thu, 12 Jan 2023 12:15:42 +0800 Subject: [PATCH 15/20] Make `TextureDescriptor` pass doctest --- wgpu-types/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 70f6fc616e..6c8416d383 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -4393,7 +4393,7 @@ impl TextureDescriptor { /// /// ```rust /// # use wgpu_types as wgpu; - /// let desc = wgpu::TextureDescriptor { + /// let desc: wgpu::TextureDescriptor<(), Vec> = wgpu::TextureDescriptor { /// label: (), /// size: wgpu::Extent3d { width: 100, height: 60, depth_or_array_layers: 1 }, /// mip_level_count: 7, From 8c491b80c27c782e6a81cef1de5aad0ed97995f8 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Thu, 12 Jan 2023 20:23:25 +0800 Subject: [PATCH 16/20] Remove DownlevelFlags::VIEW_FORMATS from gles/adapter.rs --- wgpu-hal/src/gles/adapter.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wgpu-hal/src/gles/adapter.rs b/wgpu-hal/src/gles/adapter.rs index cf19998806..833ae36d2d 100644 --- a/wgpu-hal/src/gles/adapter.rs +++ b/wgpu-hal/src/gles/adapter.rs @@ -283,8 +283,7 @@ impl super::Adapter { let mut downlevel_flags = wgt::DownlevelFlags::empty() | wgt::DownlevelFlags::NON_POWER_OF_TWO_MIPMAPPED_TEXTURES | wgt::DownlevelFlags::CUBE_ARRAY_TEXTURES - | wgt::DownlevelFlags::COMPARISON_SAMPLERS - | wgt::DownlevelFlags::VIEW_FORMATS; + | wgt::DownlevelFlags::COMPARISON_SAMPLERS; downlevel_flags.set(wgt::DownlevelFlags::COMPUTE_SHADERS, ver >= (3, 1)); downlevel_flags.set( wgt::DownlevelFlags::FRAGMENT_WRITABLE_STORAGE, From 9dd7bd174b4eaa3bda29722647f22f4d913a7c90 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Fri, 13 Jan 2023 09:00:59 +0800 Subject: [PATCH 17/20] Update wgpu-types/src/lib.rs Co-authored-by: Connor Fitzgerald --- wgpu-types/src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 6c8416d383..afbf7927f5 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -4364,8 +4364,11 @@ pub struct TextureDescriptor { pub format: TextureFormat, /// Allowed usages of the texture. If used in other ways, the operation will panic. pub usage: TextureUsages, - /// Specifies what view format values will be allowed when calling create_view() on this texture. - /// Note: currenly, only srgb-ness is allowed. + /// Specifies what view formats will be allowed when calling create_view() on this texture. + /// + /// View formats of the same format as the texture are always allowed. + /// + /// Note: currently, only the srgb-ness is allowed to change. (ex: Rgba8Unorm texture + Rgba8UnormSrgb view) pub view_formats: V, } From b00e4cd817079da098849ee5b2b067feb7f60f62 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Fri, 13 Jan 2023 09:02:36 +0800 Subject: [PATCH 18/20] Update wgpu-types/src/lib.rs Co-authored-by: Connor Fitzgerald --- wgpu-types/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index afbf7927f5..a1c4dc6018 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -4396,7 +4396,8 @@ impl TextureDescriptor { /// /// ```rust /// # use wgpu_types as wgpu; - /// let desc: wgpu::TextureDescriptor<(), Vec> = wgpu::TextureDescriptor { + /// # type TextureDescriptor = wgpu::TextureDescriptor<(), &[wgpu::TextureFormat]> + /// let desc = TextureDescriptor { /// label: (), /// size: wgpu::Extent3d { width: 100, height: 60, depth_or_array_layers: 1 }, /// mip_level_count: 7, From 247dc5c233df71432e1f4e166cfcc043c6600579 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Fri, 13 Jan 2023 10:27:48 +0800 Subject: [PATCH 19/20] impl `map_label_and_view_formats` --- wgpu-types/src/lib.rs | 18 ++++++++++++++++++ wgpu/src/backend/direct.rs | 22 ++-------------------- wgpu/src/util/device.rs | 15 ++------------- 3 files changed, 22 insertions(+), 33 deletions(-) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index a1c4dc6018..6b0dc0f3bc 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -4387,6 +4387,24 @@ impl TextureDescriptor { } } + /// Maps the label and view_formats of the texture descriptor into another. + pub fn map_label_and_view_formats( + &self, + l_fun: impl FnOnce(&L) -> K, + v_fun: impl FnOnce(V) -> M, + ) -> TextureDescriptor { + TextureDescriptor { + label: l_fun(&self.label), + size: self.size, + mip_level_count: self.mip_level_count, + sample_count: self.sample_count, + dimension: self.dimension, + format: self.format, + usage: self.usage, + view_formats: v_fun(self.view_formats.clone()), + } + } + /// Calculates the extent at a given mip level. /// /// If the given mip level is larger than possible, returns None. diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index 1221dcd878..6d5a30ecfe 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -135,16 +135,7 @@ impl Context { device: &Device, desc: &TextureDescriptor, ) -> Texture { - let descriptor = wgt::TextureDescriptor { - label: desc.label.map(Borrowed), - size: desc.size, - mip_level_count: desc.mip_level_count, - sample_count: desc.sample_count, - format: desc.format, - dimension: desc.dimension, - usage: desc.usage, - view_formats: desc.view_formats.to_vec(), - }; + let descriptor = desc.map_label_and_view_formats(|l| l.map(Borrowed), |v| v.to_vec()); let global = &self.0; let (id, error) = unsafe { global.create_texture_from_hal::(hal_texture, device.id, &descriptor, ()) }; @@ -1253,16 +1244,7 @@ impl crate::Context for Context { device_data: &Self::DeviceData, desc: &TextureDescriptor, ) -> (Self::TextureId, Self::TextureData) { - let wgt_desc = wgt::TextureDescriptor { - label: desc.label.map(Borrowed), - size: desc.size, - mip_level_count: desc.mip_level_count, - sample_count: desc.sample_count, - format: desc.format, - dimension: desc.dimension, - usage: desc.usage, - view_formats: desc.view_formats.to_vec(), - }; + let wgt_desc = desc.map_label_and_view_formats(|l| l.map(Borrowed), |v| v.to_vec()); let global = &self.0; let (id, error) = wgc::gfx_select!(device => global.device_create_texture( *device, diff --git a/wgpu/src/util/device.rs b/wgpu/src/util/device.rs index cb801d9d81..b441041a71 100644 --- a/wgpu/src/util/device.rs +++ b/wgpu/src/util/device.rs @@ -82,29 +82,18 @@ impl DeviceExt for crate::Device { desc: &crate::TextureDescriptor, data: &[u8], ) -> crate::Texture { - let wgt_desc: wgt::TextureDescriptor, Vec> = - wgt::TextureDescriptor { - label: Some(""), - size: desc.size, - mip_level_count: desc.mip_level_count, - sample_count: desc.sample_count, - format: desc.format, - dimension: desc.dimension, - usage: desc.usage, - view_formats: desc.view_formats.to_vec(), - }; // Implicitly add the COPY_DST usage let mut desc = desc.to_owned(); desc.usage |= crate::TextureUsages::COPY_DST; let texture = self.create_texture(&desc); let format_info = desc.format.describe(); - let layer_iterations = wgt_desc.array_layer_count(); + let layer_iterations = desc.array_layer_count(); let mut binary_offset = 0; for layer in 0..layer_iterations { for mip in 0..desc.mip_level_count { - let mut mip_size = wgt_desc.mip_level_size(mip).unwrap(); + let mut mip_size = desc.mip_level_size(mip).unwrap(); // copying layers separately if desc.dimension != wgt::TextureDimension::D3 { mip_size.depth_or_array_layers = 1; From 8bbccddb44b66986e345df5c10a0389888f22a87 Mon Sep 17 00:00:00 2001 From: Jinlei Li Date: Fri, 13 Jan 2023 10:50:01 +0800 Subject: [PATCH 20/20] Make pass doctest again --- wgpu-types/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 6b0dc0f3bc..5337fcd254 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -4414,7 +4414,7 @@ impl TextureDescriptor { /// /// ```rust /// # use wgpu_types as wgpu; - /// # type TextureDescriptor = wgpu::TextureDescriptor<(), &[wgpu::TextureFormat]> + /// # type TextureDescriptor<'a> = wgpu::TextureDescriptor<(), &'a [wgpu::TextureFormat]>; /// let desc = TextureDescriptor { /// label: (), /// size: wgpu::Extent3d { width: 100, height: 60, depth_or_array_layers: 1 }, @@ -4423,7 +4423,7 @@ impl TextureDescriptor { /// dimension: wgpu::TextureDimension::D3, /// format: wgpu::TextureFormat::Rgba8Sint, /// usage: wgpu::TextureUsages::empty(), - /// view_formats: vec![] + /// view_formats: &[], /// }; /// /// assert_eq!(desc.mip_level_size(0), Some(wgpu::Extent3d { width: 100, height: 60, depth_or_array_layers: 1 }));