From a33d506d95300ef784ab690dbdc7ec9c18748065 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Wed, 25 Oct 2023 20:52:46 +0800 Subject: [PATCH 01/34] support texture format nv12 --- wgpu-core/src/validation.rs | 1 + wgpu-hal/src/auxil/dxgi/conv.rs | 1 + wgpu-hal/src/dx12/adapter.rs | 3 ++- wgpu-hal/src/gles/adapter.rs | 1 + wgpu-hal/src/gles/conv.rs | 1 + wgpu-hal/src/metal/adapter.rs | 2 ++ wgpu-hal/src/vulkan/conv.rs | 1 + wgpu-types/src/lib.rs | 24 ++++++++++++++++++++++-- 8 files changed, 31 insertions(+), 3 deletions(-) diff --git a/wgpu-core/src/validation.rs b/wgpu-core/src/validation.rs index b523bf9a73..687f75e150 100644 --- a/wgpu-core/src/validation.rs +++ b/wgpu-core/src/validation.rs @@ -690,6 +690,7 @@ impl NumericType { | Tf::Depth24PlusStencil8 => { panic!("Unexpected depth format") } + Tf::NV12 => panic!("Unexpected nv12 format"), Tf::Rgb9e5Ufloat => (NumericDimension::Vector(Vs::Tri), Scalar::F32), Tf::Bc1RgbaUnorm | Tf::Bc1RgbaUnormSrgb diff --git a/wgpu-hal/src/auxil/dxgi/conv.rs b/wgpu-hal/src/auxil/dxgi/conv.rs index f3f4a18317..eb74b5adf8 100644 --- a/wgpu-hal/src/auxil/dxgi/conv.rs +++ b/wgpu-hal/src/auxil/dxgi/conv.rs @@ -62,6 +62,7 @@ pub fn map_texture_format_failable(format: wgt::TextureFormat) -> Option DXGI_FORMAT_D24_UNORM_S8_UINT, Tf::Depth32Float => DXGI_FORMAT_D32_FLOAT, Tf::Depth32FloatStencil8 => DXGI_FORMAT_D32_FLOAT_S8X24_UINT, + Tf::NV12 => DXGI_FORMAT_NV12, Tf::Bc1RgbaUnorm => DXGI_FORMAT_BC1_UNORM, Tf::Bc1RgbaUnormSrgb => DXGI_FORMAT_BC1_UNORM_SRGB, Tf::Bc2RgbaUnorm => DXGI_FORMAT_BC2_UNORM, diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index 04295508a3..c2ffda8429 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -249,7 +249,8 @@ impl super::Adapter { | wgt::Features::PUSH_CONSTANTS | wgt::Features::SHADER_PRIMITIVE_INDEX | wgt::Features::RG11B10UFLOAT_RENDERABLE - | wgt::Features::DUAL_SOURCE_BLENDING; + | wgt::Features::DUAL_SOURCE_BLENDING + | wgt::Features::TEXTURE_FORMAT_NV12; //TODO: in order to expose this, we need to run a compute shader // that extract the necessary statistics out of the D3D12 result. diff --git a/wgpu-hal/src/gles/adapter.rs b/wgpu-hal/src/gles/adapter.rs index ed1fa9cd54..b58b8dee1b 100644 --- a/wgpu-hal/src/gles/adapter.rs +++ b/wgpu-hal/src/gles/adapter.rs @@ -1073,6 +1073,7 @@ impl crate::Adapter for super::Adapter { | Tf::Depth32FloatStencil8 | Tf::Depth24Plus | Tf::Depth24PlusStencil8 => depth, + Tf::NV12 => unreachable!(), Tf::Rgb9e5Ufloat => filterable, Tf::Bc1RgbaUnorm | Tf::Bc1RgbaUnormSrgb diff --git a/wgpu-hal/src/gles/conv.rs b/wgpu-hal/src/gles/conv.rs index 3fb8383a51..ebf0c65f52 100644 --- a/wgpu-hal/src/gles/conv.rs +++ b/wgpu-hal/src/gles/conv.rs @@ -87,6 +87,7 @@ impl super::AdapterShared { glow::DEPTH_STENCIL, glow::UNSIGNED_INT_24_8, ), + Tf::NV12 => unreachable!(), Tf::Rgb9e5Ufloat => (glow::RGB9_E5, glow::RGB, glow::UNSIGNED_INT_5_9_9_9_REV), Tf::Bc1RgbaUnorm => (glow::COMPRESSED_RGBA_S3TC_DXT1_EXT, glow::RGBA, 0), Tf::Bc1RgbaUnormSrgb => (glow::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, glow::RGBA, 0), diff --git a/wgpu-hal/src/metal/adapter.rs b/wgpu-hal/src/metal/adapter.rs index 99efa280a1..752da85bc2 100644 --- a/wgpu-hal/src/metal/adapter.rs +++ b/wgpu-hal/src/metal/adapter.rs @@ -232,6 +232,7 @@ impl crate::Adapter for super::Adapter { } flags } + Tf::NV12 => unreachable!(), Tf::Rgb9e5Ufloat => { if pc.msaa_apple3 { all_caps @@ -1022,6 +1023,7 @@ impl super::PrivateCapabilities { Depth32Float_Stencil8 } } + Tf::NV12 => unreachable!(), Tf::Rgb9e5Ufloat => RGB9E5Float, Tf::Bc1RgbaUnorm => BC1_RGBA, Tf::Bc1RgbaUnormSrgb => BC1_RGBA_sRGB, diff --git a/wgpu-hal/src/vulkan/conv.rs b/wgpu-hal/src/vulkan/conv.rs index c27fdf9f72..57c6bd0a49 100644 --- a/wgpu-hal/src/vulkan/conv.rs +++ b/wgpu-hal/src/vulkan/conv.rs @@ -74,6 +74,7 @@ impl super::PrivateCapabilities { } } Tf::Depth16Unorm => F::D16_UNORM, + Tf::NV12 => unreachable!(), Tf::Rgb9e5Ufloat => F::E5B9G9R9_UFLOAT_PACK32, Tf::Bc1RgbaUnorm => F::BC1_RGBA_UNORM_BLOCK, Tf::Bc1RgbaUnormSrgb => F::BC1_RGBA_SRGB_BLOCK, diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 356eb65876..2e1aaa1339 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -771,7 +771,11 @@ bitflags::bitflags! { /// - OpenGL const SHADER_UNUSED_VERTEX_OUTPUT = 1 << 54; - // 54..59 available + /// Supported platform: + /// - DX12 + const TEXTURE_FORMAT_NV12 = 1 << 55; + + // 55..59 available // Shader: @@ -2377,6 +2381,9 @@ pub enum TextureFormat { /// [`Features::DEPTH32FLOAT_STENCIL8`] must be enabled to use this texture format. Depth32FloatStencil8, + /// + NV12, + // Compressed textures usable with `TEXTURE_COMPRESSION_BC` feature. /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 4 color + alpha pallet. 5 bit R + 6 bit G + 5 bit B + 1 bit alpha. /// [0, 63] ([0, 1] for alpha) converted to/from float [0, 1] in shader. @@ -2606,6 +2613,7 @@ impl<'de> Deserialize<'de> for TextureFormat { "depth16unorm" => TextureFormat::Depth16Unorm, "depth24plus" => TextureFormat::Depth24Plus, "depth24plus-stencil8" => TextureFormat::Depth24PlusStencil8, + "nv12" => TextureFormat::NV12, "rgb9e5ufloat" => TextureFormat::Rgb9e5Ufloat, "bc1-rgba-unorm" => TextureFormat::Bc1RgbaUnorm, "bc1-rgba-unorm-srgb" => TextureFormat::Bc1RgbaUnormSrgb, @@ -2733,6 +2741,7 @@ impl Serialize for TextureFormat { TextureFormat::Depth32FloatStencil8 => "depth32float-stencil8", TextureFormat::Depth24Plus => "depth24plus", TextureFormat::Depth24PlusStencil8 => "depth24plus-stencil8", + TextureFormat::NV12 => "nv12", TextureFormat::Rgb9e5Ufloat => "rgb9e5ufloat", TextureFormat::Bc1RgbaUnorm => "bc1-rgba-unorm", TextureFormat::Bc1RgbaUnormSrgb => "bc1-rgba-unorm-srgb", @@ -2925,7 +2934,8 @@ impl TextureFormat { | Self::Depth24Plus | Self::Depth24PlusStencil8 | Self::Depth32Float - | Self::Depth32FloatStencil8 => (1, 1), + | Self::Depth32FloatStencil8 + | Self::NV12 => (1, 1), Self::Bc1RgbaUnorm | Self::Bc1RgbaUnormSrgb @@ -3025,6 +3035,8 @@ impl TextureFormat { Self::Depth32FloatStencil8 => Features::DEPTH32FLOAT_STENCIL8, + Self::NV12 => Features::TEXTURE_FORMAT_NV12, + Self::R16Unorm | Self::R16Snorm | Self::Rg16Unorm @@ -3140,6 +3152,8 @@ impl TextureFormat { Self::Depth32Float => ( msaa, attachment), Self::Depth32FloatStencil8 => ( msaa, attachment), + Self::NV12 => ( noaa, basic), + Self::R16Unorm => ( msaa, storage), Self::R16Snorm => ( msaa, storage), Self::Rg16Unorm => ( msaa, storage), @@ -3247,6 +3261,8 @@ impl TextureFormat { Some(TextureAspect::StencilOnly) => Some(uint), }, + Self::NV12 => None, + Self::R16Unorm | Self::R16Snorm | Self::Rg16Unorm @@ -3363,6 +3379,8 @@ impl TextureFormat { Some(TextureAspect::StencilOnly) => Some(1), }, + Self::NV12 => None, + Self::Bc1RgbaUnorm | Self::Bc1RgbaUnormSrgb | Self::Bc4RUnorm | Self::Bc4RSnorm => { Some(8) } @@ -3454,6 +3472,8 @@ impl TextureFormat { TextureAspect::DepthOnly | TextureAspect::StencilOnly => 1, }, + Self::NV12 => 3, + Self::Bc4RUnorm | Self::Bc4RSnorm => 1, Self::Bc5RgUnorm | Self::Bc5RgSnorm => 2, Self::Bc6hRgbUfloat | Self::Bc6hRgbFloat => 3, From bb49d158799020f5682d7028be44833efb368a42 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Thu, 26 Oct 2023 15:39:28 +0800 Subject: [PATCH 02/34] fix view formats for nv12 texture --- wgpu-core/src/device/resource.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index d9d00bd6b3..11a424300a 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -750,6 +750,16 @@ impl Device { if desc.format == *format { continue; } + match (desc.format, *format) { + ( + TextureFormat::NV12, + TextureFormat::R8Unorm + | TextureFormat::R8Uint + | TextureFormat::Rg8Unorm + | TextureFormat::Rg8Uint, + ) => continue, + _ => {} + } if desc.format.remove_srgb_suffix() != format.remove_srgb_suffix() { return Err(CreateTextureError::InvalidViewFormat(*format, desc.format)); } From 06011028bfeaf224080588d402f33b4490060831 Mon Sep 17 00:00:00 2001 From: "lixiaopeng.jetspark" Date: Thu, 26 Oct 2023 17:39:23 +0800 Subject: [PATCH 03/34] add plane for texture view descriptor --- examples/src/mipmap/mod.rs | 1 + examples/src/shadow/mod.rs | 1 + wgpu-core/src/device/resource.rs | 7 +++++++ wgpu-core/src/present.rs | 1 + wgpu-core/src/resource.rs | 2 ++ wgpu-hal/src/dx12/view.rs | 6 ++++-- wgpu-hal/src/lib.rs | 1 + wgpu/src/backend/direct.rs | 1 + wgpu/src/lib.rs | 2 ++ 9 files changed, 20 insertions(+), 2 deletions(-) diff --git a/examples/src/mipmap/mod.rs b/examples/src/mipmap/mod.rs index c6dc7fa251..59c9aab4d4 100644 --- a/examples/src/mipmap/mod.rs +++ b/examples/src/mipmap/mod.rs @@ -133,6 +133,7 @@ impl Example { mip_level_count: Some(1), base_array_layer: 0, array_layer_count: None, + ..Default::default() }) }) .collect::>(); diff --git a/examples/src/shadow/mod.rs b/examples/src/shadow/mod.rs index 485d0d78d6..3c4aa88067 100644 --- a/examples/src/shadow/mod.rs +++ b/examples/src/shadow/mod.rs @@ -398,6 +398,7 @@ impl crate::framework::Example for Example { mip_level_count: None, base_array_layer: i as u32, array_layer_count: Some(1), + ..Default::default() })) }) .collect::>(); diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 11a424300a..56f09a1b40 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -811,6 +811,11 @@ impl Device { ); let mut clear_views = SmallVec::new(); + let plane_count = if desc.format == wgt::TextureFormat::NV12 { + 2 + } else { + 1 + }; for mip_level in 0..desc.mip_level_count { for array_layer in 0..desc.size.depth_or_array_layers { let desc = hal::TextureViewDescriptor { @@ -825,6 +830,7 @@ impl Device { base_array_layer: array_layer, array_layer_count: Some(1), }, + plane: None, }; clear_views.push(Some( unsafe { self.raw().create_texture_view(&raw_texture, &desc) } @@ -1115,6 +1121,7 @@ impl Device { dimension: resolved_dimension, usage, range: resolved_range, + plane: desc.plane, }; let raw = unsafe { diff --git a/wgpu-core/src/present.rs b/wgpu-core/src/present.rs index eb78630da2..2f86928965 100644 --- a/wgpu-core/src/present.rs +++ b/wgpu-core/src/present.rs @@ -196,6 +196,7 @@ impl Global { dimension: wgt::TextureViewDimension::D2, usage: hal::TextureUses::COLOR_TARGET, range: wgt::ImageSubresourceRange::default(), + plane: 0, }; let clear_view = unsafe { hal::Device::create_texture_view( diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index 2d4f142aff..031918c0f8 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -988,6 +988,8 @@ pub struct TextureViewDescriptor<'a> { pub dimension: Option, /// Range within the texture that is accessible via this view. pub range: wgt::ImageSubresourceRange, + /// The plane of the texture view. + pub plane: u32, } #[derive(Debug)] diff --git a/wgpu-hal/src/dx12/view.rs b/wgpu-hal/src/dx12/view.rs index e7a051b535..2bc0c692cc 100644 --- a/wgpu-hal/src/dx12/view.rs +++ b/wgpu-hal/src/dx12/view.rs @@ -14,6 +14,7 @@ pub(super) struct ViewDescriptor { array_layer_count: u32, mip_level_base: u32, mip_level_count: u32, + plane: u32, } impl crate::TextureViewDescriptor<'_> { @@ -30,6 +31,7 @@ impl crate::TextureViewDescriptor<'_> { mip_level_count: self.range.mip_level_count.unwrap_or(!0), array_layer_base: self.range.base_array_layer, array_layer_count: self.range.array_layer_count.unwrap_or(!0), + plane: self.plane, } } } @@ -79,7 +81,7 @@ impl ViewDescriptor { *desc.u.Texture2D_mut() = d3d12_ty::D3D12_TEX2D_SRV { MostDetailedMip: self.mip_level_base, MipLevels: self.mip_level_count, - PlaneSlice: 0, + PlaneSlice: self.plane, ResourceMinLODClamp: 0.0, } } @@ -103,7 +105,7 @@ impl ViewDescriptor { MipLevels: self.mip_level_count, FirstArraySlice: self.array_layer_base, ArraySize: self.array_layer_count, - PlaneSlice: 0, + PlaneSlice: self.plane, ResourceMinLODClamp: 0.0, } } diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index bc7a908ce9..d4e847690e 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -981,6 +981,7 @@ pub struct TextureViewDescriptor<'a> { pub dimension: wgt::TextureViewDimension, pub usage: TextureUses, pub range: wgt::ImageSubresourceRange, + pub plane: u32, } #[derive(Clone, Debug)] diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index 763ae4780d..1e9701634b 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -1610,6 +1610,7 @@ impl crate::Context for Context { base_array_layer: desc.base_array_layer, array_layer_count: desc.array_layer_count, }, + plane: desc.plane, }; let global = &self.0; let (id, error) = wgc::gfx_select!( diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index c85e955e7c..2a4f2d9774 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -1301,6 +1301,8 @@ pub struct TextureViewDescriptor<'a> { /// If `Some(count)`, `base_array_layer + count` must be less or equal to the underlying array count. /// If `None`, considered to include the rest of the array layers, but at least 1 in total. pub array_layer_count: Option, + /// The index (plane slice number) of the plane to use in the texture. + pub plane: u32, } static_assertions::assert_impl_all!(TextureViewDescriptor<'_>: Send, Sync); From 3c4e27f3e270670f822a08deacfc54a46220c4fe Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Thu, 26 Oct 2023 17:51:40 +0800 Subject: [PATCH 04/34] fix clippy --- wgpu-core/src/device/resource.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 56f09a1b40..baac1292a8 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -750,15 +750,15 @@ impl Device { if desc.format == *format { continue; } - match (desc.format, *format) { - ( - TextureFormat::NV12, - TextureFormat::R8Unorm - | TextureFormat::R8Uint - | TextureFormat::Rg8Unorm - | TextureFormat::Rg8Uint, - ) => continue, - _ => {} + if let ( + TextureFormat::NV12, + TextureFormat::R8Unorm + | TextureFormat::R8Uint + | TextureFormat::Rg8Unorm + | TextureFormat::Rg8Uint, + ) = (desc.format, *format) + { + continue; } if desc.format.remove_srgb_suffix() != format.remove_srgb_suffix() { return Err(CreateTextureError::InvalidViewFormat(*format, desc.format)); From af4e43427ac7c0d6b57736ded95386f3fce7d7fa Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Thu, 26 Oct 2023 18:25:46 +0800 Subject: [PATCH 05/34] comments for nv12 texture format --- wgpu-types/src/lib.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 2e1aaa1339..90744f140c 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -771,8 +771,12 @@ bitflags::bitflags! { /// - OpenGL const SHADER_UNUSED_VERTEX_OUTPUT = 1 << 54; - /// Supported platform: + /// Allows for creation of textures of format [`TextureFormat::NV12`] + /// + /// Supported platforms: /// - DX12 + /// + /// This is a native only feature. const TEXTURE_FORMAT_NV12 = 1 << 55; // 55..59 available @@ -2381,7 +2385,12 @@ pub enum TextureFormat { /// [`Features::DEPTH32FLOAT_STENCIL8`] must be enabled to use this texture format. Depth32FloatStencil8, + /// YUV 4:2:0 video resource format. + /// Valid luminance data view formats for this video resource format are [`TextureFormat::R8Unorm`] and [`TextureFormat::R8Uint`]. + /// Valid chrominance data view formats (width and height are each 1/2 of luminance view) for this video resource format are [`TextureFormat::Rg8Unorm`] and [`TextureFormat::Rg8Uint`]. + /// Width and height must be even. /// + /// [`Features::TEXTURE_FORMAT_NV12`] must be enabled to use this texture format. NV12, // Compressed textures usable with `TEXTURE_COMPRESSION_BC` feature. From 237b62d07d5f754306139c589b80ddd707d19559 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Thu, 26 Oct 2023 18:37:15 +0800 Subject: [PATCH 06/34] revert clear op for nv12 texture --- wgpu-core/src/device/resource.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index baac1292a8..f29a7a2f17 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -811,11 +811,6 @@ impl Device { ); let mut clear_views = SmallVec::new(); - let plane_count = if desc.format == wgt::TextureFormat::NV12 { - 2 - } else { - 1 - }; for mip_level in 0..desc.mip_level_count { for array_layer in 0..desc.size.depth_or_array_layers { let desc = hal::TextureViewDescriptor { From 053d38e424a95532bc6ca84a608aef29a73bfda5 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Thu, 26 Oct 2023 18:42:34 +0800 Subject: [PATCH 07/34] fix examples --- wgpu-hal/examples/halmark/main.rs | 2 ++ wgpu-hal/examples/raw-gles.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/wgpu-hal/examples/halmark/main.rs b/wgpu-hal/examples/halmark/main.rs index 609146454a..e674b4b170 100644 --- a/wgpu-hal/examples/halmark/main.rs +++ b/wgpu-hal/examples/halmark/main.rs @@ -422,6 +422,7 @@ impl Example { dimension: wgt::TextureViewDimension::D2, usage: hal::TextureUses::RESOURCE, range: wgt::ImageSubresourceRange::default(), + plane: 0, }; let texture_view = unsafe { device.create_texture_view(&texture, &view_desc).unwrap() }; @@ -658,6 +659,7 @@ impl Example { dimension: wgt::TextureViewDimension::D2, usage: hal::TextureUses::COLOR_TARGET, range: wgt::ImageSubresourceRange::default(), + plane: 0, }; let surface_tex_view = unsafe { self.device diff --git a/wgpu-hal/examples/raw-gles.rs b/wgpu-hal/examples/raw-gles.rs index 81ab4171e3..4ef0724858 100644 --- a/wgpu-hal/examples/raw-gles.rs +++ b/wgpu-hal/examples/raw-gles.rs @@ -142,6 +142,7 @@ fn fill_screen(exposed: &hal::ExposedAdapter, width: u32, height dimension: wgt::TextureViewDimension::D2, usage: hal::TextureUses::COLOR_TARGET, range: wgt::ImageSubresourceRange::default(), + plane: 0, }, ) .unwrap() From af28fe30233cd04145cd67e75a9c45b4514dbee4 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Thu, 26 Oct 2023 18:48:25 +0800 Subject: [PATCH 08/34] fix tests --- tests/tests/bgra8unorm_storage.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/tests/bgra8unorm_storage.rs b/tests/tests/bgra8unorm_storage.rs index 5cfcb27a29..0caf7f80e3 100644 --- a/tests/tests/bgra8unorm_storage.rs +++ b/tests/tests/bgra8unorm_storage.rs @@ -49,6 +49,7 @@ static BGRA8_UNORM_STORAGE: GpuTestConfiguration = GpuTestConfiguration::new() base_array_layer: 0, mip_level_count: Some(1), array_layer_count: Some(1), + ..Default::default() }); let readback_buffer = device.create_buffer(&wgpu::BufferDescriptor { From c28a4add417aa3dfd00e947179b597f95551657c Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Thu, 26 Oct 2023 18:53:53 +0800 Subject: [PATCH 09/34] fix op_webgpu_create_texture_view --- deno_webgpu/texture.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/deno_webgpu/texture.rs b/deno_webgpu/texture.rs index 5eadd5b3c2..c18f44ca89 100644 --- a/deno_webgpu/texture.rs +++ b/deno_webgpu/texture.rs @@ -124,6 +124,7 @@ pub fn op_webgpu_create_texture_view( format: args.format, dimension: args.dimension, range: args.range, + plane: 0, }; gfx_put!(texture => instance.texture_create_view( From 2f072f22e1fd091b20e0dcf949e765d9fccd7166 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Fri, 27 Oct 2023 20:20:00 +0800 Subject: [PATCH 10/34] support nv12 texture for vulkan --- wgpu-hal/src/vulkan/adapter.rs | 14 ++++++++++++++ wgpu-hal/src/vulkan/conv.rs | 23 ++++++++++++++++++----- wgpu-hal/src/vulkan/device.rs | 3 ++- wgpu-types/src/lib.rs | 1 + 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index 5b1cf2fccf..21af1c84b4 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -535,6 +535,20 @@ impl PhysicalDeviceFeatures { supports_bgra8unorm_storage(instance, phd, caps.device_api_version), ); + features.set( + F::TEXTURE_FORMAT_NV12, + supports_format( + instance, + phd, + vk::Format::G8_B8R8_2PLANE_420_UNORM, + vk::ImageTiling::OPTIMAL, + vk::FormatFeatureFlags::SAMPLED_IMAGE + | vk::FormatFeatureFlags::STORAGE_IMAGE + | vk::FormatFeatureFlags::TRANSFER_SRC + | vk::FormatFeatureFlags::TRANSFER_DST, + ), + ); + (features, dl_flags) } diff --git a/wgpu-hal/src/vulkan/conv.rs b/wgpu-hal/src/vulkan/conv.rs index 57c6bd0a49..dbbe8868e2 100644 --- a/wgpu-hal/src/vulkan/conv.rs +++ b/wgpu-hal/src/vulkan/conv.rs @@ -1,5 +1,11 @@ use ash::vk; +// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkImageAspectFlagBits.html +const VK_IMAGE_ASPECT_NONE: vk::Flags = 0; +const VK_IMAGE_ASPECT_PLANE_0_BIT: vk::Flags = 0x00000010; +const VK_IMAGE_ASPECT_PLANE_1_BIT: vk::Flags = 0x00000020; +const VK_IMAGE_ASPECT_PLANE_2_BIT: vk::Flags = 0x00000040; + impl super::PrivateCapabilities { pub fn map_texture_format(&self, format: wgt::TextureFormat) -> vk::Format { use ash::vk::Format as F; @@ -74,7 +80,7 @@ impl super::PrivateCapabilities { } } Tf::Depth16Unorm => F::D16_UNORM, - Tf::NV12 => unreachable!(), + Tf::NV12 => F::G8_B8R8_2PLANE_420_UNORM, Tf::Rgb9e5Ufloat => F::E5B9G9R9_UFLOAT_PACK32, Tf::Bc1RgbaUnorm => F::BC1_RGBA_UNORM_BLOCK, Tf::Bc1RgbaUnormSrgb => F::BC1_RGBA_SRGB_BLOCK, @@ -402,7 +408,7 @@ pub fn map_vertex_format(vertex_format: wgt::VertexFormat) -> vk::Format { } } -pub fn map_aspects(aspects: crate::FormatAspects) -> vk::ImageAspectFlags { +pub fn map_aspects(aspects: crate::FormatAspects, plane: Option) -> vk::ImageAspectFlags { let mut flags = vk::ImageAspectFlags::empty(); if aspects.contains(crate::FormatAspects::COLOR) { flags |= vk::ImageAspectFlags::COLOR; @@ -413,6 +419,12 @@ pub fn map_aspects(aspects: crate::FormatAspects) -> vk::ImageAspectFlags { if aspects.contains(crate::FormatAspects::STENCIL) { flags |= vk::ImageAspectFlags::STENCIL; } + flags |= vk::ImageAspectFlags::from_raw(match plane { + Some(0) => VK_IMAGE_ASPECT_PLANE_0_BIT, + Some(1) => VK_IMAGE_ASPECT_PLANE_1_BIT, + Some(2) => VK_IMAGE_ASPECT_PLANE_2_BIT, + _ => VK_IMAGE_ASPECT_NONE, + }); flags } @@ -587,9 +599,10 @@ pub fn map_copy_extent(extent: &crate::CopyExtent) -> vk::Extent3D { pub fn map_subresource_range( range: &wgt::ImageSubresourceRange, format: wgt::TextureFormat, + plane: Option, ) -> vk::ImageSubresourceRange { vk::ImageSubresourceRange { - aspect_mask: map_aspects(crate::FormatAspects::new(format, range.aspect)), + aspect_mask: map_aspects(crate::FormatAspects::new(format, range.aspect), plane), base_mip_level: range.base_mip_level, level_count: range.mip_level_count.unwrap_or(vk::REMAINING_MIP_LEVELS), base_array_layer: range.base_array_layer, @@ -606,7 +619,7 @@ pub(super) fn map_subresource_range_combined_aspect( format: wgt::TextureFormat, private_caps: &super::PrivateCapabilities, ) -> vk::ImageSubresourceRange { - let mut range = map_subresource_range(range, format); + let mut range = map_subresource_range(range, format, None); if !private_caps.texture_s8 && format == wgt::TextureFormat::Stencil8 { range.aspect_mask |= vk::ImageAspectFlags::DEPTH; } @@ -622,7 +635,7 @@ pub fn map_subresource_layers( z: base.origin.z as i32, }; let subresource = vk::ImageSubresourceLayers { - aspect_mask: map_aspects(base.aspect), + aspect_mask: map_aspects(base.aspect, None), mip_level: base.mip_level, base_array_layer: base.array_layer, layer_count: 1, diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index 5f7fbac47a..3bd55933de 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -1062,7 +1062,8 @@ impl crate::Device for super::Device { texture: &super::Texture, desc: &crate::TextureViewDescriptor, ) -> Result { - let subresource_range = conv::map_subresource_range(&desc.range, desc.format); + let subresource_range = + conv::map_subresource_range(&desc.range, desc.format, Some(desc.plane)); let mut vk_info = vk::ImageViewCreateInfo::builder() .flags(vk::ImageViewCreateFlags::empty()) .image(texture.raw) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 90744f140c..4b8cdb0426 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -775,6 +775,7 @@ bitflags::bitflags! { /// /// Supported platforms: /// - DX12 + /// - Vulkan /// /// This is a native only feature. const TEXTURE_FORMAT_NV12 = 1 << 55; From a321e5fb9b2f0ec881fac3cec329f2b9d23d5ef8 Mon Sep 17 00:00:00 2001 From: "lixiaopeng.jetspark" Date: Fri, 27 Oct 2023 21:01:07 +0800 Subject: [PATCH 11/34] fix TEXTURE_FORMAT_NV12 feature for vulkan --- wgpu-hal/src/vulkan/adapter.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index 21af1c84b4..16c210db8c 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -543,7 +543,6 @@ impl PhysicalDeviceFeatures { vk::Format::G8_B8R8_2PLANE_420_UNORM, vk::ImageTiling::OPTIMAL, vk::FormatFeatureFlags::SAMPLED_IMAGE - | vk::FormatFeatureFlags::STORAGE_IMAGE | vk::FormatFeatureFlags::TRANSFER_SRC | vk::FormatFeatureFlags::TRANSFER_DST, ), @@ -1565,14 +1564,14 @@ impl crate::Adapter for super::Adapter { .framebuffer_stencil_sample_counts .min(limits.sampled_image_stencil_sample_counts) } else { - match format.sample_type(None).unwrap() { - wgt::TextureSampleType::Float { filterable: _ } => limits + match format.sample_type(None) { + Some(wgt::TextureSampleType::Float { filterable: _ }) => limits .framebuffer_color_sample_counts .min(limits.sampled_image_color_sample_counts), - wgt::TextureSampleType::Sint | wgt::TextureSampleType::Uint => { + Some(wgt::TextureSampleType::Sint) | Some(wgt::TextureSampleType::Uint) => { limits.sampled_image_integer_sample_counts } - _ => unreachable!(), + _ => vk::SampleCountFlags::TYPE_1, } }; From cc39129303e7cdc7e353640bbd6092e70c618ec5 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Mon, 30 Oct 2023 16:21:16 +0800 Subject: [PATCH 12/34] only support texture binding usage for nv12 format --- wgpu-types/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 4b8cdb0426..2ce24c4524 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -3101,6 +3101,7 @@ impl TextureFormat { TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING; let attachment = basic | TextureUsages::RENDER_ATTACHMENT; let storage = basic | TextureUsages::STORAGE_BINDING; + let binding = TextureUsages::TEXTURE_BINDING; let all_flags = TextureUsages::all(); let rg11b10f = if device_features.contains(Features::RG11B10UFLOAT_RENDERABLE) { attachment @@ -3162,7 +3163,8 @@ impl TextureFormat { Self::Depth32Float => ( msaa, attachment), Self::Depth32FloatStencil8 => ( msaa, attachment), - Self::NV12 => ( noaa, basic), + // We only support sampling nv12 textures until we implement transfer plane data. + Self::NV12 => ( noaa, binding), Self::R16Unorm => ( msaa, storage), Self::R16Snorm => ( msaa, storage), From f9dcef29f98adf4c89fcac5d3f106898c1c5de57 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Mon, 30 Oct 2023 17:42:44 +0800 Subject: [PATCH 13/34] add nv12_texture test --- tests/tests/nv12_texture/mod.rs | 119 +++++++++++++++++++++ tests/tests/nv12_texture/nv12_texture.wgsl | 33 ++++++ tests/tests/root.rs | 1 + 3 files changed, 153 insertions(+) create mode 100644 tests/tests/nv12_texture/mod.rs create mode 100644 tests/tests/nv12_texture/nv12_texture.wgsl diff --git a/tests/tests/nv12_texture/mod.rs b/tests/tests/nv12_texture/mod.rs new file mode 100644 index 0000000000..b3a4272191 --- /dev/null +++ b/tests/tests/nv12_texture/mod.rs @@ -0,0 +1,119 @@ +//! Tests for nv12 texture creation and sampling. + +use wgpu_test::{gpu_test, GpuTestConfiguration, TestParameters}; + +#[gpu_test] +static NV12_TEXTURE_CREATION_SAMPLING: GpuTestConfiguration = GpuTestConfiguration::new() + .parameters(TestParameters::default().features(wgpu::Features::TEXTURE_FORMAT_NV12)) + .run_sync(|ctx| { + let size = wgpu::Extent3d { + width: 256, + height: 256, + depth_or_array_layers: 1, + }; + let target_format = wgpu::TextureFormat::Bgra8UnormSrgb; + + let shader = ctx + .device + .create_shader_module(wgpu::include_wgsl!("nv12_texture.wgsl")); + let pipeline = ctx + .device + .create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("nv12 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(target_format.into())], + }), + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleStrip, + strip_index_format: Some(wgpu::IndexFormat::Uint32), + ..Default::default() + }, + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + multiview: None, + }); + + let tex = ctx.device.create_texture(&wgpu::TextureDescriptor { + label: None, + dimension: wgpu::TextureDimension::D2, + size, + format: wgpu::TextureFormat::NV12, + usage: wgpu::TextureUsages::TEXTURE_BINDING, + mip_level_count: 1, + sample_count: 1, + view_formats: &[wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::Rg8Unorm], + }); + let y_view = tex.create_view(&wgpu::TextureViewDescriptor { + format: Some(wgpu::TextureFormat::R8Unorm), + plane: 0, + ..Default::default() + }); + let uv_view = tex.create_view(&wgpu::TextureViewDescriptor { + format: Some(wgpu::TextureFormat::Rg8Unorm), + plane: 1, + ..Default::default() + }); + let sampler = ctx.device.create_sampler(&wgpu::SamplerDescriptor { + min_filter: wgpu::FilterMode::Linear, + mag_filter: wgpu::FilterMode::Linear, + ..Default::default() + }); + let bind_group = ctx.device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &pipeline.get_bind_group_layout(0), + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::Sampler(&sampler), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::TextureView(&y_view), + }, + wgpu::BindGroupEntry { + binding: 2, + resource: wgpu::BindingResource::TextureView(&uv_view), + }, + ], + }); + + let target_tex = ctx.device.create_texture(&wgpu::TextureDescriptor { + label: None, + size, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: target_format, + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + view_formats: &[], + }); + let target_view = target_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 { + label: None, + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + ops: wgpu::Operations::default(), + resolve_target: None, + view: &target_view, + })], + depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, + }); + rpass.set_pipeline(&pipeline); + rpass.set_bind_group(0, &bind_group, &[]); + rpass.draw(0..4, 0..1); + drop(rpass); + ctx.queue.submit(Some(encoder.finish())); + }); diff --git a/tests/tests/nv12_texture/nv12_texture.wgsl b/tests/tests/nv12_texture/nv12_texture.wgsl new file mode 100644 index 0000000000..0787440560 --- /dev/null +++ b/tests/tests/nv12_texture/nv12_texture.wgsl @@ -0,0 +1,33 @@ +struct VertexOutput { + @builtin(position) pos: vec4, + uv: vec2, +} + +@vertex +fn vs_main(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput { + var output: VertexOutput; + // 0, 0 + // 2, 0 + // 0, 2 + // 2, 2 + let v_data = vec2(f32((vertexIndex << 1u) & 2u), f32(vertexIndex & 2u)); + output.pos = vec4(v_data - 1.0, 0.0, 1.0); + output.uv = v_data / 2.0; + return output; +} + +@group(0) @binding(0) var s: sampler; +@group(0) @binding(1) var tex_y: texture_2d; +@group(0) @binding(2) var tex_uv: texture_2d; + +@fragment +fn fs_main(v_ouput: VertexOutput) -> @location(0) vec4 { + let luminance = textureSample(tex_y, s, v_ouput.uv).r; + let chrominance = textureSample(tex_uv, s, v_ouput.uv).rg; + let rgb = mat3x3( + 1.000000, 1.000000, 1.000000, + 0.000000,-0.187324, 1.855600, + 1.574800,-0.468124, 0.000000, + ) * vec3(luminance, chrominance.r - 0.5, chrominance.g - 0.5); + return vec4(rgb, 1.0); +} diff --git a/tests/tests/root.rs b/tests/tests/root.rs index fbb56a7b2f..5fd119b2c9 100644 --- a/tests/tests/root.rs +++ b/tests/tests/root.rs @@ -18,6 +18,7 @@ mod external_texture; mod instance; mod life_cycle; mod mem_leaks; +mod nv12_texture; mod occlusion_query; mod partially_bounded_arrays; mod pipeline; From b6b0d53d10fb5926b10a886bfc14928e8b968b25 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Mon, 30 Oct 2023 17:57:19 +0800 Subject: [PATCH 14/34] fix shader --- tests/tests/nv12_texture/nv12_texture.wgsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests/nv12_texture/nv12_texture.wgsl b/tests/tests/nv12_texture/nv12_texture.wgsl index 0787440560..ea974100b1 100644 --- a/tests/tests/nv12_texture/nv12_texture.wgsl +++ b/tests/tests/nv12_texture/nv12_texture.wgsl @@ -1,6 +1,6 @@ struct VertexOutput { @builtin(position) pos: vec4, - uv: vec2, + @location(0) uv: vec2, } @vertex From f0fd394cd75707b1c5a449e455cfdb9f652fa3ca Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Mon, 30 Oct 2023 18:12:41 +0800 Subject: [PATCH 15/34] make plane optional --- deno_webgpu/texture.rs | 2 +- tests/tests/nv12_texture/mod.rs | 4 ++-- wgpu-core/src/present.rs | 2 +- wgpu-core/src/resource.rs | 2 +- wgpu-hal/examples/halmark/main.rs | 4 ++-- wgpu-hal/examples/raw-gles.rs | 2 +- wgpu-hal/src/lib.rs | 2 +- wgpu-hal/src/vulkan/device.rs | 3 +-- wgpu/src/lib.rs | 2 +- 9 files changed, 11 insertions(+), 12 deletions(-) diff --git a/deno_webgpu/texture.rs b/deno_webgpu/texture.rs index c18f44ca89..fb9640f59f 100644 --- a/deno_webgpu/texture.rs +++ b/deno_webgpu/texture.rs @@ -124,7 +124,7 @@ pub fn op_webgpu_create_texture_view( format: args.format, dimension: args.dimension, range: args.range, - plane: 0, + plane: None, }; gfx_put!(texture => instance.texture_create_view( diff --git a/tests/tests/nv12_texture/mod.rs b/tests/tests/nv12_texture/mod.rs index b3a4272191..99f1302d27 100644 --- a/tests/tests/nv12_texture/mod.rs +++ b/tests/tests/nv12_texture/mod.rs @@ -53,12 +53,12 @@ static NV12_TEXTURE_CREATION_SAMPLING: GpuTestConfiguration = GpuTestConfigurati }); let y_view = tex.create_view(&wgpu::TextureViewDescriptor { format: Some(wgpu::TextureFormat::R8Unorm), - plane: 0, + plane: Some(0), ..Default::default() }); let uv_view = tex.create_view(&wgpu::TextureViewDescriptor { format: Some(wgpu::TextureFormat::Rg8Unorm), - plane: 1, + plane: Some(1), ..Default::default() }); let sampler = ctx.device.create_sampler(&wgpu::SamplerDescriptor { diff --git a/wgpu-core/src/present.rs b/wgpu-core/src/present.rs index 2f86928965..fe76fdc8ed 100644 --- a/wgpu-core/src/present.rs +++ b/wgpu-core/src/present.rs @@ -196,7 +196,7 @@ impl Global { dimension: wgt::TextureViewDimension::D2, usage: hal::TextureUses::COLOR_TARGET, range: wgt::ImageSubresourceRange::default(), - plane: 0, + plane: None, }; let clear_view = unsafe { hal::Device::create_texture_view( diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index 031918c0f8..ae575e9ae5 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -989,7 +989,7 @@ pub struct TextureViewDescriptor<'a> { /// Range within the texture that is accessible via this view. pub range: wgt::ImageSubresourceRange, /// The plane of the texture view. - pub plane: u32, + pub plane: Option, } #[derive(Debug)] diff --git a/wgpu-hal/examples/halmark/main.rs b/wgpu-hal/examples/halmark/main.rs index e674b4b170..60b2c144f2 100644 --- a/wgpu-hal/examples/halmark/main.rs +++ b/wgpu-hal/examples/halmark/main.rs @@ -422,7 +422,7 @@ impl Example { dimension: wgt::TextureViewDimension::D2, usage: hal::TextureUses::RESOURCE, range: wgt::ImageSubresourceRange::default(), - plane: 0, + plane: None, }; let texture_view = unsafe { device.create_texture_view(&texture, &view_desc).unwrap() }; @@ -659,7 +659,7 @@ impl Example { dimension: wgt::TextureViewDimension::D2, usage: hal::TextureUses::COLOR_TARGET, range: wgt::ImageSubresourceRange::default(), - plane: 0, + plane: None, }; let surface_tex_view = unsafe { self.device diff --git a/wgpu-hal/examples/raw-gles.rs b/wgpu-hal/examples/raw-gles.rs index 4ef0724858..71e08443ea 100644 --- a/wgpu-hal/examples/raw-gles.rs +++ b/wgpu-hal/examples/raw-gles.rs @@ -142,7 +142,7 @@ fn fill_screen(exposed: &hal::ExposedAdapter, width: u32, height dimension: wgt::TextureViewDimension::D2, usage: hal::TextureUses::COLOR_TARGET, range: wgt::ImageSubresourceRange::default(), - plane: 0, + plane: None, }, ) .unwrap() diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index d4e847690e..fb4aaf2580 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -981,7 +981,7 @@ pub struct TextureViewDescriptor<'a> { pub dimension: wgt::TextureViewDimension, pub usage: TextureUses, pub range: wgt::ImageSubresourceRange, - pub plane: u32, + pub plane: Option, } #[derive(Clone, Debug)] diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index 3bd55933de..d9aba50281 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -1062,8 +1062,7 @@ impl crate::Device for super::Device { texture: &super::Texture, desc: &crate::TextureViewDescriptor, ) -> Result { - let subresource_range = - conv::map_subresource_range(&desc.range, desc.format, Some(desc.plane)); + let subresource_range = conv::map_subresource_range(&desc.range, desc.format, desc.plane); let mut vk_info = vk::ImageViewCreateInfo::builder() .flags(vk::ImageViewCreateFlags::empty()) .image(texture.raw) diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 2a4f2d9774..639d02e728 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -1302,7 +1302,7 @@ pub struct TextureViewDescriptor<'a> { /// If `None`, considered to include the rest of the array layers, but at least 1 in total. pub array_layer_count: Option, /// The index (plane slice number) of the plane to use in the texture. - pub plane: u32, + pub plane: Option, } static_assertions::assert_impl_all!(TextureViewDescriptor<'_>: Send, Sync); From 8e9cdb3ba40f0f69b5cd8c1bcde4766bf10b2813 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Mon, 30 Oct 2023 18:36:41 +0800 Subject: [PATCH 16/34] vulkan: prefer plane flags --- wgpu-hal/src/dx12/view.rs | 2 +- wgpu-hal/src/vulkan/conv.rs | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/wgpu-hal/src/dx12/view.rs b/wgpu-hal/src/dx12/view.rs index 2bc0c692cc..630fc149d6 100644 --- a/wgpu-hal/src/dx12/view.rs +++ b/wgpu-hal/src/dx12/view.rs @@ -31,7 +31,7 @@ impl crate::TextureViewDescriptor<'_> { mip_level_count: self.range.mip_level_count.unwrap_or(!0), array_layer_base: self.range.base_array_layer, array_layer_count: self.range.array_layer_count.unwrap_or(!0), - plane: self.plane, + plane: self.plane.unwrap_or(0), } } } diff --git a/wgpu-hal/src/vulkan/conv.rs b/wgpu-hal/src/vulkan/conv.rs index dbbe8868e2..aa309a2f69 100644 --- a/wgpu-hal/src/vulkan/conv.rs +++ b/wgpu-hal/src/vulkan/conv.rs @@ -1,7 +1,6 @@ use ash::vk; // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkImageAspectFlagBits.html -const VK_IMAGE_ASPECT_NONE: vk::Flags = 0; const VK_IMAGE_ASPECT_PLANE_0_BIT: vk::Flags = 0x00000010; const VK_IMAGE_ASPECT_PLANE_1_BIT: vk::Flags = 0x00000020; const VK_IMAGE_ASPECT_PLANE_2_BIT: vk::Flags = 0x00000040; @@ -410,8 +409,14 @@ pub fn map_vertex_format(vertex_format: wgt::VertexFormat) -> vk::Format { pub fn map_aspects(aspects: crate::FormatAspects, plane: Option) -> vk::ImageAspectFlags { let mut flags = vk::ImageAspectFlags::empty(); - if aspects.contains(crate::FormatAspects::COLOR) { - flags |= vk::ImageAspectFlags::COLOR; + match plane { + Some(0) => flags |= vk::ImageAspectFlags::from_raw(VK_IMAGE_ASPECT_PLANE_0_BIT), + Some(1) => flags |= vk::ImageAspectFlags::from_raw(VK_IMAGE_ASPECT_PLANE_1_BIT), + Some(2) => flags |= vk::ImageAspectFlags::from_raw(VK_IMAGE_ASPECT_PLANE_2_BIT), + _ if aspects.contains(crate::FormatAspects::COLOR) => { + flags |= vk::ImageAspectFlags::COLOR; + } + _ => {} } if aspects.contains(crate::FormatAspects::DEPTH) { flags |= vk::ImageAspectFlags::DEPTH; @@ -419,12 +424,6 @@ pub fn map_aspects(aspects: crate::FormatAspects, plane: Option) -> vk::Ima if aspects.contains(crate::FormatAspects::STENCIL) { flags |= vk::ImageAspectFlags::STENCIL; } - flags |= vk::ImageAspectFlags::from_raw(match plane { - Some(0) => VK_IMAGE_ASPECT_PLANE_0_BIT, - Some(1) => VK_IMAGE_ASPECT_PLANE_1_BIT, - Some(2) => VK_IMAGE_ASPECT_PLANE_2_BIT, - _ => VK_IMAGE_ASPECT_NONE, - }); flags } From 6eaea3ce5bfc280dadb50bc36eafb6db098207fa Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Mon, 30 Oct 2023 18:55:16 +0800 Subject: [PATCH 17/34] fix hal view formats --- wgpu-core/src/device/resource.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index f29a7a2f17..232cf06649 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -750,17 +750,18 @@ impl Device { if desc.format == *format { continue; } - if let ( - TextureFormat::NV12, - TextureFormat::R8Unorm - | TextureFormat::R8Uint - | TextureFormat::Rg8Unorm - | TextureFormat::Rg8Uint, - ) = (desc.format, *format) + + if !matches!( + (desc.format, *format), + ( + TextureFormat::NV12, + TextureFormat::R8Unorm + | TextureFormat::R8Uint + | TextureFormat::Rg8Unorm + | TextureFormat::Rg8Uint, + ) + ) && desc.format.remove_srgb_suffix() != format.remove_srgb_suffix() { - continue; - } - if desc.format.remove_srgb_suffix() != format.remove_srgb_suffix() { return Err(CreateTextureError::InvalidViewFormat(*format, desc.format)); } hal_view_formats.push(*format); From baf9e82d50df893efdc188912106736f349415e5 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Mon, 30 Oct 2023 19:45:13 +0800 Subject: [PATCH 18/34] skip clear nv12 textures --- wgpu-core/src/command/clear.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wgpu-core/src/command/clear.rs b/wgpu-core/src/command/clear.rs index 5405c926e5..73ffaec9f2 100644 --- a/wgpu-core/src/command/clear.rs +++ b/wgpu-core/src/command/clear.rs @@ -337,6 +337,11 @@ fn clear_texture_via_buffer_copies( hal::FormatAspects::COLOR ); + if texture_desc.format == wgt::TextureFormat::NV12 { + // TODO: Currently COPY_DST for NV12 textures is unsupported. + return Ok(()); + } + // Gather list of zero_buffer copies and issue a single command then to perform them let mut zero_buffer_copy_regions = Vec::new(); let buffer_copy_pitch = alignments.buffer_copy_pitch.get() as u32; From eb4ebdd4d50646f16a8fc1480f969164142ee5fe Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Mon, 30 Oct 2023 20:35:56 +0800 Subject: [PATCH 19/34] fix clippy --- wgpu-core/src/command/clear.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wgpu-core/src/command/clear.rs b/wgpu-core/src/command/clear.rs index 73ffaec9f2..620911c181 100644 --- a/wgpu-core/src/command/clear.rs +++ b/wgpu-core/src/command/clear.rs @@ -339,7 +339,7 @@ fn clear_texture_via_buffer_copies( if texture_desc.format == wgt::TextureFormat::NV12 { // TODO: Currently COPY_DST for NV12 textures is unsupported. - return Ok(()); + return; } // Gather list of zero_buffer copies and issue a single command then to perform them From d934e09cf86c0442b458b9b146f31520b2076b09 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Wed, 1 Nov 2023 16:07:13 +0800 Subject: [PATCH 20/34] disable TEXTURE_FORMAT_NV12 on macOS/iOS --- wgpu-hal/src/vulkan/adapter.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index 16c210db8c..7862a008e4 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -535,6 +535,8 @@ impl PhysicalDeviceFeatures { supports_bgra8unorm_storage(instance, phd, caps.device_api_version), ); + // https://github.com/KhronosGroup/MoltenVK/issues/440 + #[cfg(not(any(target_os = "macos", target_os = "ios")))] features.set( F::TEXTURE_FORMAT_NV12, supports_format( From c5da3d6a2e34b46fabf69bb669beb1ca701c3b51 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Mon, 13 Nov 2023 14:32:04 +0800 Subject: [PATCH 21/34] check vulkan api version and extension --- wgpu-hal/src/vulkan/adapter.rs | 13 ++----------- wgpu-hal/src/vulkan/conv.rs | 11 +++-------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index 7862a008e4..954fee7f9e 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -535,19 +535,10 @@ impl PhysicalDeviceFeatures { supports_bgra8unorm_storage(instance, phd, caps.device_api_version), ); - // https://github.com/KhronosGroup/MoltenVK/issues/440 - #[cfg(not(any(target_os = "macos", target_os = "ios")))] features.set( F::TEXTURE_FORMAT_NV12, - supports_format( - instance, - phd, - vk::Format::G8_B8R8_2PLANE_420_UNORM, - vk::ImageTiling::OPTIMAL, - vk::FormatFeatureFlags::SAMPLED_IMAGE - | vk::FormatFeatureFlags::TRANSFER_SRC - | vk::FormatFeatureFlags::TRANSFER_DST, - ), + caps.device_api_version >= vk::API_VERSION_1_1 + || caps.supports_extension(vk::KhrSamplerYcbcrConversionFn::name()), ); (features, dl_flags) diff --git a/wgpu-hal/src/vulkan/conv.rs b/wgpu-hal/src/vulkan/conv.rs index aa309a2f69..49d3308a5d 100644 --- a/wgpu-hal/src/vulkan/conv.rs +++ b/wgpu-hal/src/vulkan/conv.rs @@ -1,10 +1,5 @@ use ash::vk; -// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkImageAspectFlagBits.html -const VK_IMAGE_ASPECT_PLANE_0_BIT: vk::Flags = 0x00000010; -const VK_IMAGE_ASPECT_PLANE_1_BIT: vk::Flags = 0x00000020; -const VK_IMAGE_ASPECT_PLANE_2_BIT: vk::Flags = 0x00000040; - impl super::PrivateCapabilities { pub fn map_texture_format(&self, format: wgt::TextureFormat) -> vk::Format { use ash::vk::Format as F; @@ -410,9 +405,9 @@ pub fn map_vertex_format(vertex_format: wgt::VertexFormat) -> vk::Format { pub fn map_aspects(aspects: crate::FormatAspects, plane: Option) -> vk::ImageAspectFlags { let mut flags = vk::ImageAspectFlags::empty(); match plane { - Some(0) => flags |= vk::ImageAspectFlags::from_raw(VK_IMAGE_ASPECT_PLANE_0_BIT), - Some(1) => flags |= vk::ImageAspectFlags::from_raw(VK_IMAGE_ASPECT_PLANE_1_BIT), - Some(2) => flags |= vk::ImageAspectFlags::from_raw(VK_IMAGE_ASPECT_PLANE_2_BIT), + Some(0) => flags |= vk::ImageAspectFlags::PLANE_0, + Some(1) => flags |= vk::ImageAspectFlags::PLANE_1, + Some(2) => flags |= vk::ImageAspectFlags::PLANE_2, _ if aspects.contains(crate::FormatAspects::COLOR) => { flags |= vk::ImageAspectFlags::COLOR; } From 618d16694157b8433d4faa3d56d3e2ff9a3b824f Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Tue, 14 Nov 2023 17:47:59 +0800 Subject: [PATCH 22/34] check supports format --- wgpu-hal/src/vulkan/adapter.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index 954fee7f9e..3a8ec7040c 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -537,8 +537,17 @@ impl PhysicalDeviceFeatures { features.set( F::TEXTURE_FORMAT_NV12, - caps.device_api_version >= vk::API_VERSION_1_1 - || caps.supports_extension(vk::KhrSamplerYcbcrConversionFn::name()), + (caps.device_api_version >= vk::API_VERSION_1_1 + || caps.supports_extension(vk::KhrSamplerYcbcrConversionFn::name())) + && supports_format( + instance, + phd, + vk::Format::G8_B8R8_2PLANE_420_UNORM, + vk::ImageTiling::OPTIMAL, + vk::FormatFeatureFlags::SAMPLED_IMAGE + | vk::FormatFeatureFlags::TRANSFER_SRC + | vk::FormatFeatureFlags::TRANSFER_DST, + ), ); (features, dl_flags) From 0f3043423d27522908659710b5e709087ef2b813 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Thu, 16 Nov 2023 14:57:37 +0800 Subject: [PATCH 23/34] add fn check_texture_view_format_compatible --- wgpu-core/src/device/resource.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 232cf06649..31a36bb296 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -751,17 +751,7 @@ impl Device { continue; } - if !matches!( - (desc.format, *format), - ( - TextureFormat::NV12, - TextureFormat::R8Unorm - | TextureFormat::R8Uint - | TextureFormat::Rg8Unorm - | TextureFormat::Rg8Uint, - ) - ) && desc.format.remove_srgb_suffix() != format.remove_srgb_suffix() - { + if !check_texture_view_format_compatible(desc.format, *format) { return Err(CreateTextureError::InvalidViewFormat(*format, desc.format)); } hal_view_formats.push(*format); @@ -3361,3 +3351,15 @@ impl Resource for Device { &mut self.info } } + +fn check_texture_view_format_compatible( + texture_format: TextureFormat, + view_format: TextureFormat, +) -> bool { + use TextureFormat::*; + + match (texture_format, view_format) { + (NV12, R8Unorm | R8Uint | Rg8Unorm | Rg8Uint) => true, + _ => texture_format.remove_srgb_suffix() == view_format.remove_srgb_suffix(), + } +} From 5af70e855197a33670ed485d98c5ab97c6d100fc Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Thu, 16 Nov 2023 15:56:31 +0800 Subject: [PATCH 24/34] check unexpected plane value for vulkan --- wgpu-hal/src/vulkan/conv.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/wgpu-hal/src/vulkan/conv.rs b/wgpu-hal/src/vulkan/conv.rs index 49d3308a5d..e2d33b20e7 100644 --- a/wgpu-hal/src/vulkan/conv.rs +++ b/wgpu-hal/src/vulkan/conv.rs @@ -408,10 +408,12 @@ pub fn map_aspects(aspects: crate::FormatAspects, plane: Option) -> vk::Ima Some(0) => flags |= vk::ImageAspectFlags::PLANE_0, Some(1) => flags |= vk::ImageAspectFlags::PLANE_1, Some(2) => flags |= vk::ImageAspectFlags::PLANE_2, - _ if aspects.contains(crate::FormatAspects::COLOR) => { - flags |= vk::ImageAspectFlags::COLOR; + Some(plane) => panic!("Unexpected plane {}", plane), + None => { + if aspects.contains(crate::FormatAspects::COLOR) { + flags |= vk::ImageAspectFlags::COLOR; + } } - _ => {} } if aspects.contains(crate::FormatAspects::DEPTH) { flags |= vk::ImageAspectFlags::DEPTH; From 42fee025f43daf8a0c8fd9ee1082cf22a1735967 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Thu, 16 Nov 2023 15:56:44 +0800 Subject: [PATCH 25/34] add more tests for nv12 texture --- tests/tests/nv12_texture/mod.rs | 120 +++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) diff --git a/tests/tests/nv12_texture/mod.rs b/tests/tests/nv12_texture/mod.rs index 99f1302d27..310e60374d 100644 --- a/tests/tests/nv12_texture/mod.rs +++ b/tests/tests/nv12_texture/mod.rs @@ -1,6 +1,6 @@ //! Tests for nv12 texture creation and sampling. -use wgpu_test::{gpu_test, GpuTestConfiguration, TestParameters}; +use wgpu_test::{gpu_test, FailureCase, GpuTestConfiguration, TestParameters}; #[gpu_test] static NV12_TEXTURE_CREATION_SAMPLING: GpuTestConfiguration = GpuTestConfiguration::new() @@ -117,3 +117,121 @@ static NV12_TEXTURE_CREATION_SAMPLING: GpuTestConfiguration = GpuTestConfigurati drop(rpass); ctx.queue.submit(Some(encoder.finish())); }); + +#[gpu_test] +static NV12_TEXTURE_CREATION_BAD_VIEW_FORMATS: GpuTestConfiguration = GpuTestConfiguration::new() + .parameters( + TestParameters::default() + .features(wgpu::Features::TEXTURE_FORMAT_NV12) + .expect_fail(FailureCase::always()), + ) + .run_sync(|ctx| { + let size = wgpu::Extent3d { + width: 256, + height: 256, + depth_or_array_layers: 1, + }; + let _ = ctx.device.create_texture(&wgpu::TextureDescriptor { + label: None, + dimension: wgpu::TextureDimension::D2, + size, + format: wgpu::TextureFormat::NV12, + usage: wgpu::TextureUsages::TEXTURE_BINDING, + mip_level_count: 1, + sample_count: 1, + view_formats: &[wgpu::TextureFormat::Rgba8Unorm], + }); + }); + +/// For D3D12 backend, textures always have plane 0 +#[gpu_test] +static NV12_TEXTURE_VIEW_PLANE_ON_NON_PLANAR_FORMAT: GpuTestConfiguration = + GpuTestConfiguration::new() + .parameters( + TestParameters::default() + .features(wgpu::Features::TEXTURE_FORMAT_NV12) + .expect_fail(FailureCase::backend( + wgpu::Backends::all().remove(wgpu::Backends::DX12), + )), + ) + .run_sync(|ctx| { + let size = wgpu::Extent3d { + width: 256, + height: 256, + depth_or_array_layers: 1, + }; + let tex = ctx.device.create_texture(&wgpu::TextureDescriptor { + label: None, + dimension: wgpu::TextureDimension::D2, + size, + format: wgpu::TextureFormat::R8Unorm, + usage: wgpu::TextureUsages::TEXTURE_BINDING, + mip_level_count: 1, + sample_count: 1, + view_formats: &[], + }); + let _ = tex.create_view(&wgpu::TextureViewDescriptor { + plane: Some(0), + ..Default::default() + }); + }); + +#[gpu_test] +static NV12_TEXTURE_VIEW_PLANE_OUT_OF_BOUNDS: GpuTestConfiguration = GpuTestConfiguration::new() + .parameters( + TestParameters::default() + .features(wgpu::Features::TEXTURE_FORMAT_NV12) + .expect_fail(FailureCase::always()), + ) + .run_sync(|ctx| { + let size = wgpu::Extent3d { + width: 256, + height: 256, + depth_or_array_layers: 1, + }; + let tex = ctx.device.create_texture(&wgpu::TextureDescriptor { + label: None, + dimension: wgpu::TextureDimension::D2, + size, + format: wgpu::TextureFormat::NV12, + usage: wgpu::TextureUsages::TEXTURE_BINDING, + mip_level_count: 1, + sample_count: 1, + view_formats: &[wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::Rg8Unorm], + }); + let _ = tex.create_view(&wgpu::TextureViewDescriptor { + format: Some(wgpu::TextureFormat::R8Unorm), + plane: Some(2), + ..Default::default() + }); + }); + +#[gpu_test] +static NV12_TEXTURE_BAD_FORMAT_VIEW_PLANE: GpuTestConfiguration = GpuTestConfiguration::new() + .parameters( + TestParameters::default() + .features(wgpu::Features::TEXTURE_FORMAT_NV12) + .expect_fail(FailureCase::always()), + ) + .run_sync(|ctx| { + let size = wgpu::Extent3d { + width: 256, + height: 256, + depth_or_array_layers: 1, + }; + let tex = ctx.device.create_texture(&wgpu::TextureDescriptor { + label: None, + dimension: wgpu::TextureDimension::D2, + size, + format: wgpu::TextureFormat::NV12, + usage: wgpu::TextureUsages::TEXTURE_BINDING, + mip_level_count: 1, + sample_count: 1, + view_formats: &[wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::Rg8Unorm], + }); + let _ = tex.create_view(&wgpu::TextureViewDescriptor { + format: Some(wgpu::TextureFormat::R8gUnorm), + plane: Some(0), + ..Default::default() + }); + }); From c03f1604ce360525aa8d008a28bfc86194a65fb6 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Thu, 16 Nov 2023 16:04:04 +0800 Subject: [PATCH 26/34] fix clippy --- tests/tests/nv12_texture/mod.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/tests/nv12_texture/mod.rs b/tests/tests/nv12_texture/mod.rs index 310e60374d..eb4881dd92 100644 --- a/tests/tests/nv12_texture/mod.rs +++ b/tests/tests/nv12_texture/mod.rs @@ -143,16 +143,18 @@ static NV12_TEXTURE_CREATION_BAD_VIEW_FORMATS: GpuTestConfiguration = GpuTestCon }); }); -/// For D3D12 backend, textures always have plane 0 +/// For DX11/DX12 backend, textures always have plane 0 #[gpu_test] static NV12_TEXTURE_VIEW_PLANE_ON_NON_PLANAR_FORMAT: GpuTestConfiguration = GpuTestConfiguration::new() .parameters( TestParameters::default() .features(wgpu::Features::TEXTURE_FORMAT_NV12) - .expect_fail(FailureCase::backend( - wgpu::Backends::all().remove(wgpu::Backends::DX12), - )), + .expect_fail(FailureCase::backend({ + let mut backends = wgpu::Backends::all(); + backends.remove(wgpu::Backends::DX11 | wgpu::Backends::DX12); + backends + })), ) .run_sync(|ctx| { let size = wgpu::Extent3d { @@ -230,7 +232,7 @@ static NV12_TEXTURE_BAD_FORMAT_VIEW_PLANE: GpuTestConfiguration = GpuTestConfigu view_formats: &[wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::Rg8Unorm], }); let _ = tex.create_view(&wgpu::TextureViewDescriptor { - format: Some(wgpu::TextureFormat::R8gUnorm), + format: Some(wgpu::TextureFormat::Rg8Unorm), plane: Some(0), ..Default::default() }); From 1982e4518d566396870d458ba74876cd0b0e3230 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Thu, 16 Nov 2023 16:49:52 +0800 Subject: [PATCH 27/34] disable nv12 feature for MoltenVK --- wgpu-hal/src/vulkan/adapter.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index 3a8ec7040c..d065286546 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -301,6 +301,7 @@ impl PhysicalDeviceFeatures { fn to_wgpu( &self, + adapter_info: &wgt::AdapterInfo, instance: &ash::Instance, phd: vk::PhysicalDevice, caps: &PhysicalDeviceCapabilities, @@ -547,7 +548,8 @@ impl PhysicalDeviceFeatures { vk::FormatFeatureFlags::SAMPLED_IMAGE | vk::FormatFeatureFlags::TRANSFER_SRC | vk::FormatFeatureFlags::TRANSFER_DST, - ), + ) + && !adapter_info.driver.contains("moltenvk"), ); (features, dl_flags) @@ -984,7 +986,7 @@ impl super::Instance { }; let (available_features, downlevel_flags) = - phd_features.to_wgpu(&self.shared.raw, phd, &phd_capabilities); + phd_features.to_wgpu(&info, &self.shared.raw, phd, &phd_capabilities); let mut workarounds = super::Workarounds::empty(); { // see https://github.com/gfx-rs/gfx/issues/1930 From 1df8c8d22109b957408c5a6a5dfade92a8ba169f Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Thu, 16 Nov 2023 16:53:24 +0800 Subject: [PATCH 28/34] fix MoltenVK driver name --- wgpu-hal/src/vulkan/adapter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index d065286546..0af87eb072 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -549,7 +549,7 @@ impl PhysicalDeviceFeatures { | vk::FormatFeatureFlags::TRANSFER_SRC | vk::FormatFeatureFlags::TRANSFER_DST, ) - && !adapter_info.driver.contains("moltenvk"), + && !adapter_info.driver.contains("MoltenVK"), ); (features, dl_flags) From 9a9d5900be1c11f72595ecf8b8570363d7352794 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Fri, 17 Nov 2023 12:33:57 +0800 Subject: [PATCH 29/34] validate texture view plane --- tests/tests/nv12_texture/mod.rs | 79 +++++++++++++------------------- wgpu-core/src/device/resource.rs | 28 +++++++++++ wgpu-core/src/resource.rs | 10 ++++ wgpu-hal/src/metal/adapter.rs | 2 +- 4 files changed, 72 insertions(+), 47 deletions(-) diff --git a/tests/tests/nv12_texture/mod.rs b/tests/tests/nv12_texture/mod.rs index eb4881dd92..e8c0455c82 100644 --- a/tests/tests/nv12_texture/mod.rs +++ b/tests/tests/nv12_texture/mod.rs @@ -1,6 +1,6 @@ //! Tests for nv12 texture creation and sampling. -use wgpu_test::{gpu_test, FailureCase, GpuTestConfiguration, TestParameters}; +use wgpu_test::{fail, gpu_test, GpuTestConfiguration, TestParameters}; #[gpu_test] static NV12_TEXTURE_CREATION_SAMPLING: GpuTestConfiguration = GpuTestConfiguration::new() @@ -120,42 +120,31 @@ static NV12_TEXTURE_CREATION_SAMPLING: GpuTestConfiguration = GpuTestConfigurati #[gpu_test] static NV12_TEXTURE_CREATION_BAD_VIEW_FORMATS: GpuTestConfiguration = GpuTestConfiguration::new() - .parameters( - TestParameters::default() - .features(wgpu::Features::TEXTURE_FORMAT_NV12) - .expect_fail(FailureCase::always()), - ) + .parameters(TestParameters::default().features(wgpu::Features::TEXTURE_FORMAT_NV12)) .run_sync(|ctx| { let size = wgpu::Extent3d { width: 256, height: 256, depth_or_array_layers: 1, }; - let _ = ctx.device.create_texture(&wgpu::TextureDescriptor { - label: None, - dimension: wgpu::TextureDimension::D2, - size, - format: wgpu::TextureFormat::NV12, - usage: wgpu::TextureUsages::TEXTURE_BINDING, - mip_level_count: 1, - sample_count: 1, - view_formats: &[wgpu::TextureFormat::Rgba8Unorm], + fail(&ctx.device, || { + let _ = ctx.device.create_texture(&wgpu::TextureDescriptor { + label: None, + dimension: wgpu::TextureDimension::D2, + size, + format: wgpu::TextureFormat::NV12, + usage: wgpu::TextureUsages::TEXTURE_BINDING, + mip_level_count: 1, + sample_count: 1, + view_formats: &[wgpu::TextureFormat::Rgba8Unorm], + }); }); }); -/// For DX11/DX12 backend, textures always have plane 0 #[gpu_test] static NV12_TEXTURE_VIEW_PLANE_ON_NON_PLANAR_FORMAT: GpuTestConfiguration = GpuTestConfiguration::new() - .parameters( - TestParameters::default() - .features(wgpu::Features::TEXTURE_FORMAT_NV12) - .expect_fail(FailureCase::backend({ - let mut backends = wgpu::Backends::all(); - backends.remove(wgpu::Backends::DX11 | wgpu::Backends::DX12); - backends - })), - ) + .parameters(TestParameters::default().features(wgpu::Features::TEXTURE_FORMAT_NV12)) .run_sync(|ctx| { let size = wgpu::Extent3d { width: 256, @@ -172,19 +161,17 @@ static NV12_TEXTURE_VIEW_PLANE_ON_NON_PLANAR_FORMAT: GpuTestConfiguration = sample_count: 1, view_formats: &[], }); - let _ = tex.create_view(&wgpu::TextureViewDescriptor { - plane: Some(0), - ..Default::default() + fail(&ctx.device, || { + let _ = tex.create_view(&wgpu::TextureViewDescriptor { + plane: Some(0), + ..Default::default() + }); }); }); #[gpu_test] static NV12_TEXTURE_VIEW_PLANE_OUT_OF_BOUNDS: GpuTestConfiguration = GpuTestConfiguration::new() - .parameters( - TestParameters::default() - .features(wgpu::Features::TEXTURE_FORMAT_NV12) - .expect_fail(FailureCase::always()), - ) + .parameters(TestParameters::default().features(wgpu::Features::TEXTURE_FORMAT_NV12)) .run_sync(|ctx| { let size = wgpu::Extent3d { width: 256, @@ -201,20 +188,18 @@ static NV12_TEXTURE_VIEW_PLANE_OUT_OF_BOUNDS: GpuTestConfiguration = GpuTestConf sample_count: 1, view_formats: &[wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::Rg8Unorm], }); - let _ = tex.create_view(&wgpu::TextureViewDescriptor { - format: Some(wgpu::TextureFormat::R8Unorm), - plane: Some(2), - ..Default::default() + fail(&ctx.device, || { + let _ = tex.create_view(&wgpu::TextureViewDescriptor { + format: Some(wgpu::TextureFormat::R8Unorm), + plane: Some(2), + ..Default::default() + }); }); }); #[gpu_test] static NV12_TEXTURE_BAD_FORMAT_VIEW_PLANE: GpuTestConfiguration = GpuTestConfiguration::new() - .parameters( - TestParameters::default() - .features(wgpu::Features::TEXTURE_FORMAT_NV12) - .expect_fail(FailureCase::always()), - ) + .parameters(TestParameters::default().features(wgpu::Features::TEXTURE_FORMAT_NV12)) .run_sync(|ctx| { let size = wgpu::Extent3d { width: 256, @@ -231,9 +216,11 @@ static NV12_TEXTURE_BAD_FORMAT_VIEW_PLANE: GpuTestConfiguration = GpuTestConfigu sample_count: 1, view_formats: &[wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::Rg8Unorm], }); - let _ = tex.create_view(&wgpu::TextureViewDescriptor { - format: Some(wgpu::TextureFormat::Rg8Unorm), - plane: Some(0), - ..Default::default() + fail(&ctx.device, || { + let _ = tex.create_view(&wgpu::TextureViewDescriptor { + format: Some(wgpu::TextureFormat::Rg8Unorm), + plane: Some(0), + ..Default::default() + }); }); }); diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 31a36bb296..cf58c8e965 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -1016,6 +1016,34 @@ impl Device { }); }; + match (texture.desc.format, resolved_format, desc.plane) { + ( + wgt::TextureFormat::NV12, + wgt::TextureFormat::R8Unorm | wgt::TextureFormat::R8Uint, + Some(0), + ) => {} + ( + wgt::TextureFormat::NV12, + wgt::TextureFormat::Rg8Unorm | wgt::TextureFormat::Rg8Uint, + Some(1), + ) => {} + (wgt::TextureFormat::NV12, _, _) => { + return Err(resource::CreateTextureViewError::InvalidTextureViewPlane { + plane: desc.plane, + view_format: resolved_format, + }); + } + (_, _, Some(_)) => { + return Err( + resource::CreateTextureViewError::InvalidTextureViewPlaneOnNonplanarTexture { + plane: desc.plane, + texture_format: texture.desc.format, + }, + ); + } + _ => {} + } + // https://gpuweb.github.io/gpuweb/#abstract-opdef-renderable-texture-view let render_extent = 'b: loop { if !texture diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index ae575e9ae5..49d36a7acc 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -1100,6 +1100,16 @@ pub enum CreateTextureViewError { texture: wgt::TextureFormat, view: wgt::TextureFormat, }, + #[error("Invalid texture view plane `{plane:?}` with view format `{view_format:?}`")] + InvalidTextureViewPlane { + plane: Option, + view_format: wgt::TextureFormat, + }, + #[error("Invalid texture view plane `{plane:?}` on non-planar texture `{texture_format:?}`")] + InvalidTextureViewPlaneOnNonplanarTexture { + plane: Option, + texture_format: wgt::TextureFormat, + }, } #[derive(Clone, Debug, Error)] diff --git a/wgpu-hal/src/metal/adapter.rs b/wgpu-hal/src/metal/adapter.rs index 752da85bc2..e05091053a 100644 --- a/wgpu-hal/src/metal/adapter.rs +++ b/wgpu-hal/src/metal/adapter.rs @@ -232,7 +232,7 @@ impl crate::Adapter for super::Adapter { } flags } - Tf::NV12 => unreachable!(), + Tf::NV12 => return Tfc::empty(), Tf::Rgb9e5Ufloat => { if pc.msaa_apple3 { all_caps From adb8ad1b981bee803354297a5ba4dfaf05d66000 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Fri, 17 Nov 2023 12:52:08 +0800 Subject: [PATCH 30/34] add validate_texture_view_plane --- wgpu-core/src/device/resource.rs | 52 +++++++++++++++----------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index cf58c8e965..9057c901da 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -1016,33 +1016,7 @@ impl Device { }); }; - match (texture.desc.format, resolved_format, desc.plane) { - ( - wgt::TextureFormat::NV12, - wgt::TextureFormat::R8Unorm | wgt::TextureFormat::R8Uint, - Some(0), - ) => {} - ( - wgt::TextureFormat::NV12, - wgt::TextureFormat::Rg8Unorm | wgt::TextureFormat::Rg8Uint, - Some(1), - ) => {} - (wgt::TextureFormat::NV12, _, _) => { - return Err(resource::CreateTextureViewError::InvalidTextureViewPlane { - plane: desc.plane, - view_format: resolved_format, - }); - } - (_, _, Some(_)) => { - return Err( - resource::CreateTextureViewError::InvalidTextureViewPlaneOnNonplanarTexture { - plane: desc.plane, - texture_format: texture.desc.format, - }, - ); - } - _ => {} - } + validate_texture_view_plane(texture.desc.format, resolved_format, desc.plane)?; // https://gpuweb.github.io/gpuweb/#abstract-opdef-renderable-texture-view let render_extent = 'b: loop { @@ -3391,3 +3365,27 @@ fn check_texture_view_format_compatible( _ => texture_format.remove_srgb_suffix() == view_format.remove_srgb_suffix(), } } + +fn validate_texture_view_plane( + texture_format: TextureFormat, + view_format: TextureFormat, + plane: Option, +) -> Result<(), resource::CreateTextureViewError> { + use TextureFormat::*; + + match (texture_format, view_format, plane) { + (NV12, R8Unorm | R8Uint, Some(0)) => Ok(()), + (NV12, Rg8Unorm | Rg8Uint, Some(1)) => Ok(()), + (NV12, _, _) => { + Err(resource::CreateTextureViewError::InvalidTextureViewPlane { plane, view_format }) + } + + (_, _, Some(_)) => Err( + resource::CreateTextureViewError::InvalidTextureViewPlaneOnNonplanarTexture { + plane, + texture_format, + }, + ), + _ => Ok(()), + } +} From 2ee63218a13698e0cd16a2e7a1f8e7ebefcb84fc Mon Sep 17 00:00:00 2001 From: Xiaopeng Li Date: Mon, 20 Nov 2023 10:17:09 +0800 Subject: [PATCH 31/34] Update wgpu-types/src/lib.rs Co-authored-by: Connor Fitzgerald --- wgpu-types/src/lib.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 2ce24c4524..6880cbff2b 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -2386,9 +2386,16 @@ pub enum TextureFormat { /// [`Features::DEPTH32FLOAT_STENCIL8`] must be enabled to use this texture format. Depth32FloatStencil8, - /// YUV 4:2:0 video resource format. - /// Valid luminance data view formats for this video resource format are [`TextureFormat::R8Unorm`] and [`TextureFormat::R8Uint`]. - /// Valid chrominance data view formats (width and height are each 1/2 of luminance view) for this video resource format are [`TextureFormat::Rg8Unorm`] and [`TextureFormat::Rg8Uint`]. + /// YUV 4:2:0 chroma subsampled format. + /// + /// Contains two planes: + /// - 0: Single 8 bit channel luminance. + /// - 1: Dual 8 bit channel chrominance at half width and half height. + /// + /// Valid view formats for luminance are [`TextureFormat::R8Unorm`] and [`TextureFormat::R8Uint`]. + /// + /// Valid view formats for chrominance are [`TextureFormat::Rg8Unorm`] and [`TextureFormat::Rg8Uint`]. + /// /// Width and height must be even. /// /// [`Features::TEXTURE_FORMAT_NV12`] must be enabled to use this texture format. From 5e2f54727d2c1029c56b4909dd144519016b9603 Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Mon, 20 Nov 2023 11:14:43 +0800 Subject: [PATCH 32/34] treat NV12's block size as (2, 2) --- wgpu-types/src/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 6880cbff2b..3e9ab37a24 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -2393,7 +2393,7 @@ pub enum TextureFormat { /// - 1: Dual 8 bit channel chrominance at half width and half height. /// /// Valid view formats for luminance are [`TextureFormat::R8Unorm`] and [`TextureFormat::R8Uint`]. - /// + /// /// Valid view formats for chrominance are [`TextureFormat::Rg8Unorm`] and [`TextureFormat::Rg8Uint`]. /// /// Width and height must be even. @@ -2951,8 +2951,9 @@ impl TextureFormat { | Self::Depth24Plus | Self::Depth24PlusStencil8 | Self::Depth32Float - | Self::Depth32FloatStencil8 - | Self::NV12 => (1, 1), + | Self::Depth32FloatStencil8 => (1, 1), + + Self::NV12 => (2, 2), Self::Bc1RgbaUnorm | Self::Bc1RgbaUnormSrgb From 26693969dfec21f61277433f12894f8218b0b01d Mon Sep 17 00:00:00 2001 From: xiaopengli89 Date: Mon, 20 Nov 2023 11:19:53 +0800 Subject: [PATCH 33/34] add NV12_TEXTURE_BAD_SIZE test --- tests/tests/nv12_texture/mod.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/tests/nv12_texture/mod.rs b/tests/tests/nv12_texture/mod.rs index e8c0455c82..0d9b4b5d4d 100644 --- a/tests/tests/nv12_texture/mod.rs +++ b/tests/tests/nv12_texture/mod.rs @@ -224,3 +224,27 @@ static NV12_TEXTURE_BAD_FORMAT_VIEW_PLANE: GpuTestConfiguration = GpuTestConfigu }); }); }); + +#[gpu_test] +static NV12_TEXTURE_BAD_SIZE: GpuTestConfiguration = GpuTestConfiguration::new() + .parameters(TestParameters::default().features(wgpu::Features::TEXTURE_FORMAT_NV12)) + .run_sync(|ctx| { + let size = wgpu::Extent3d { + width: 255, + height: 255, + depth_or_array_layers: 1, + }; + + fail(&ctx.device, || { + let _ = ctx.device.create_texture(&wgpu::TextureDescriptor { + label: None, + dimension: wgpu::TextureDimension::D2, + size, + format: wgpu::TextureFormat::NV12, + usage: wgpu::TextureUsages::TEXTURE_BINDING, + mip_level_count: 1, + sample_count: 1, + view_formats: &[wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::Rg8Unorm], + }); + }); + }); From 89bc7cff16cd849338f1cfef50e87d0951fd75bd Mon Sep 17 00:00:00 2001 From: "lixiaopeng.jetspark" Date: Fri, 24 Nov 2023 13:33:26 +0800 Subject: [PATCH 34/34] fix rebase --- wgpu-core/src/device/resource.rs | 47 ++++++++++++++++++++------------ wgpu-hal/src/dx12/device.rs | 6 +++- wgpu-hal/src/dx12/view.rs | 8 +++--- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 9057c901da..6d2e140a8b 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -804,24 +804,35 @@ impl Device { let mut clear_views = SmallVec::new(); for mip_level in 0..desc.mip_level_count { for array_layer in 0..desc.size.depth_or_array_layers { - let desc = hal::TextureViewDescriptor { - label: clear_label, - format: desc.format, - dimension, - usage, - range: wgt::ImageSubresourceRange { - aspect: wgt::TextureAspect::All, - base_mip_level: mip_level, - mip_level_count: Some(1), - base_array_layer: array_layer, - array_layer_count: Some(1), - }, - plane: None, - }; - clear_views.push(Some( - unsafe { self.raw().create_texture_view(&raw_texture, &desc) } - .map_err(DeviceError::from)?, - )); + macro_rules! push_clear_view { + ($format:expr, $plane:expr) => { + let desc = hal::TextureViewDescriptor { + label: clear_label, + format: $format, + dimension, + usage, + range: wgt::ImageSubresourceRange { + aspect: wgt::TextureAspect::All, + base_mip_level: mip_level, + mip_level_count: Some(1), + base_array_layer: array_layer, + array_layer_count: Some(1), + }, + plane: $plane, + }; + clear_views.push(Some( + unsafe { self.raw().create_texture_view(&raw_texture, &desc) } + .map_err(DeviceError::from)?, + )); + }; + } + + if desc.format == wgt::TextureFormat::NV12 { + push_clear_view!(wgt::TextureFormat::R8Unorm, Some(0)); + push_clear_view!(wgt::TextureFormat::Rg8Unorm, Some(1)); + } else { + push_clear_view!(desc.format, None); + } } } resource::TextureClearMode::RenderPass { diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 649fdb4f8b..90af93661e 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -467,7 +467,11 @@ impl crate::Device for super::Device { aspects: view_desc.aspects, target_base: ( texture.resource.clone(), - texture.calc_subresource(desc.range.base_mip_level, desc.range.base_array_layer, 0), + texture.calc_subresource( + desc.range.base_mip_level, + desc.range.base_array_layer, + desc.plane.unwrap_or(0), + ), ), handle_srv: if desc.usage.intersects(crate::TextureUses::RESOURCE) { let raw_desc = unsafe { view_desc.to_srv() }; diff --git a/wgpu-hal/src/dx12/view.rs b/wgpu-hal/src/dx12/view.rs index 630fc149d6..9a597e464c 100644 --- a/wgpu-hal/src/dx12/view.rs +++ b/wgpu-hal/src/dx12/view.rs @@ -181,7 +181,7 @@ impl ViewDescriptor { unsafe { *desc.u.Texture2D_mut() = d3d12_ty::D3D12_TEX2D_UAV { MipSlice: self.mip_level_base, - PlaneSlice: 0, + PlaneSlice: self.plane, } } } @@ -192,7 +192,7 @@ impl ViewDescriptor { MipSlice: self.mip_level_base, FirstArraySlice: self.array_layer_base, ArraySize: self.array_layer_count, - PlaneSlice: 0, + PlaneSlice: self.plane, } } } @@ -252,7 +252,7 @@ impl ViewDescriptor { unsafe { *desc.u.Texture2D_mut() = d3d12_ty::D3D12_TEX2D_RTV { MipSlice: self.mip_level_base, - PlaneSlice: 0, + PlaneSlice: self.plane, } } } @@ -274,7 +274,7 @@ impl ViewDescriptor { MipSlice: self.mip_level_base, FirstArraySlice: self.array_layer_base, ArraySize: self.array_layer_count, - PlaneSlice: 0, + PlaneSlice: self.plane, } } }