From 84f226f37afea55677097ac24f5c789d2df53ccd Mon Sep 17 00:00:00 2001 From: khyperia Date: Wed, 4 Aug 2021 13:46:26 +0200 Subject: [PATCH 1/6] Add sample_bias function --- crates/spirv-std/src/image.rs | 33 +++++++++++++++++++++++++++++++++ tests/ui/image/sample_bias.rs | 20 ++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 tests/ui/image/sample_bias.rs diff --git a/crates/spirv-std/src/image.rs b/crates/spirv-std/src/image.rs index 2070a81266..6f98e51c5c 100644 --- a/crates/spirv-std/src/image.rs +++ b/crates/spirv-std/src/image.rs @@ -162,6 +162,39 @@ impl< } } + /// Sample texels at `coord` from the image using `sampler`, after adding the input bias to the + /// implicit level of detail. + #[crate::macros::gpu_only] + pub fn sample_bias( + &self, + sampler: Sampler, + coord: impl ImageCoordinate, + bias: f32, + ) -> V + where + F: Float, + V: Vector, + { + unsafe { + let mut result = Default::default(); + asm!( + "%typeSampledImage = OpTypeSampledImage typeof*{1}", + "%image = OpLoad typeof*{1} {1}", + "%sampler = OpLoad typeof*{2} {2}", + "%coord = OpLoad typeof*{3} {3}", + "%sampledImage = OpSampledImage %typeSampledImage %image %sampler", + "%result = OpImageSampleImplicitLod typeof*{0} %sampledImage %coord Bias {4}", + "OpStore {0} %result", + in(reg) &mut result, + in(reg) self, + in(reg) &sampler, + in(reg) &coord, + in(reg) bias, + ); + result + } + } + /// Fetch a single texel with a sampler set at compile time #[crate::macros::gpu_only] #[doc(alias = "OpImageSampleExplicitLod")] diff --git a/tests/ui/image/sample_bias.rs b/tests/ui/image/sample_bias.rs new file mode 100644 index 0000000000..85e652c75f --- /dev/null +++ b/tests/ui/image/sample_bias.rs @@ -0,0 +1,20 @@ +// Test `OpImageSampleImplicitLod` Bias +// build-pass + +use spirv_std::{arch, Image, Sampler}; + +#[spirv(fragment)] +pub fn main( + #[spirv(descriptor_set = 0, binding = 0)] image2d: &Image!(2D, type=f32, sampled), + #[spirv(descriptor_set = 1, binding = 1)] image2d_array: &Image!(2D, type=f32, arrayed, sampled), + #[spirv(descriptor_set = 2, binding = 2)] cubemap: &Image!(3D, type=f32, sampled), + #[spirv(descriptor_set = 3, binding = 3)] sampler: &Sampler, + output: &mut glam::Vec4, +) { + let v2 = glam::Vec2::new(0.0, 1.0); + let v3 = glam::Vec3::new(0.0, 1.0, 0.5); + let r1: glam::Vec4 = image2d.sample_bias(*sampler, v2, 0.0); + let r2: glam::Vec4 = image2d_array.sample_bias(*sampler, v3, 0.0); + let r3: glam::Vec4 = cubemap.sample_bias(*sampler, v3, 0.0); + *output = r1 + r2 + r3; +} From 09e1856429478807ca874658d51dc8e13dc366e4 Mon Sep 17 00:00:00 2001 From: khyperia Date: Wed, 4 Aug 2021 13:58:49 +0200 Subject: [PATCH 2/6] Update line numbers --- tests/ui/image/query/query_levels_err.stderr | 14 +++++++------- tests/ui/image/query/query_lod_err.stderr | 14 +++++++------- tests/ui/image/query/query_size_err.stderr | 16 ++++++++-------- tests/ui/image/query/query_size_lod_err.stderr | 14 +++++++------- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/tests/ui/image/query/query_levels_err.stderr b/tests/ui/image/query/query_levels_err.stderr index 95e9eae88c..a520f86ca6 100644 --- a/tests/ui/image/query/query_levels_err.stderr +++ b/tests/ui/image/query/query_levels_err.stderr @@ -1,12 +1,12 @@ error: OpImageQueryLevels's image has a dimension of DimRect - --> $SPIRV_STD_SRC/image.rs:763:13 + --> $SPIRV_STD_SRC/image.rs:796:13 | -763 | / asm! { -764 | | "%image = OpLoad _ {this}", -765 | | "{result} = OpImageQueryLevels typeof{result} %image", -766 | | this = in(reg) self, -767 | | result = out(reg) result, -768 | | } +796 | / asm! { +797 | | "%image = OpLoad _ {this}", +798 | | "{result} = OpImageQueryLevels typeof{result} %image", +799 | | this = in(reg) self, +800 | | result = out(reg) result, +801 | | } | |_____________^ | = note: Allowed dimensions are 1D, 2D, 3D, and Cube diff --git a/tests/ui/image/query/query_lod_err.stderr b/tests/ui/image/query/query_lod_err.stderr index 03f6c7f014..057d9139b0 100644 --- a/tests/ui/image/query/query_lod_err.stderr +++ b/tests/ui/image/query/query_lod_err.stderr @@ -1,13 +1,13 @@ error: OpImageQueryLod's image has a dimension of DimRect - --> $SPIRV_STD_SRC/image.rs:796:13 + --> $SPIRV_STD_SRC/image.rs:829:13 | -796 | / asm! { -797 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}", -798 | | "%image = OpLoad _ {this}", -799 | | "%sampler = OpLoad _ {sampler}", +829 | / asm! { +830 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}", +831 | | "%image = OpLoad _ {this}", +832 | | "%sampler = OpLoad _ {sampler}", ... | -807 | | coord = in(reg) &coord -808 | | } +840 | | coord = in(reg) &coord +841 | | } | |_____________^ | = note: Allowed dimensions are 1D, 2D, 3D, and Cube diff --git a/tests/ui/image/query/query_size_err.stderr b/tests/ui/image/query/query_size_err.stderr index 63dd9de844..541414bc12 100644 --- a/tests/ui/image/query/query_size_err.stderr +++ b/tests/ui/image/query/query_size_err.stderr @@ -1,13 +1,13 @@ error: OpImageQuerySize is invalid for this image type - --> $SPIRV_STD_SRC/image.rs:825:13 + --> $SPIRV_STD_SRC/image.rs:858:13 | -825 | / asm! { -826 | | "%image = OpLoad _ {this}", -827 | | "%result = OpImageQuerySize typeof*{result} %image", -828 | | "OpStore {result} %result", -829 | | this = in(reg) self, -830 | | result = in(reg) &mut result, -831 | | } +858 | / asm! { +859 | | "%image = OpLoad _ {this}", +860 | | "%result = OpImageQuerySize typeof*{result} %image", +861 | | "OpStore {result} %result", +862 | | this = in(reg) self, +863 | | result = in(reg) &mut result, +864 | | } | |_____________^ | = note: allowed dimensions are 1D, 2D, 3D, Buffer, Rect, or Cube. if dimension is 1D, 2D, 3D, or Cube, it must have either multisampled be true, *or* sampled of Unknown or No diff --git a/tests/ui/image/query/query_size_lod_err.stderr b/tests/ui/image/query/query_size_lod_err.stderr index a45d563603..c5dbe23ad1 100644 --- a/tests/ui/image/query/query_size_lod_err.stderr +++ b/tests/ui/image/query/query_size_lod_err.stderr @@ -1,13 +1,13 @@ error: OpImageQuerySizeLod is invalid for this image type - --> $SPIRV_STD_SRC/image.rs:871:13 + --> $SPIRV_STD_SRC/image.rs:904:13 | -871 | / asm! { -872 | | "%image = OpLoad _ {this}", -873 | | "%result = OpImageQuerySizeLod typeof*{result} %image {lod}", -874 | | "OpStore {result} %result", +904 | / asm! { +905 | | "%image = OpLoad _ {this}", +906 | | "%result = OpImageQuerySizeLod typeof*{result} %image {lod}", +907 | | "OpStore {result} %result", ... | -877 | | result = in(reg) &mut result, -878 | | } +910 | | result = in(reg) &mut result, +911 | | } | |_____________^ | = note: The image's dimension must be 1D, 2D, 3D, or Cube. Multisampled must be false. From 2ab98a386739dd6a42697ccd76a29f4bb9d7babd Mon Sep 17 00:00:00 2001 From: khyperia Date: Thu, 5 Aug 2021 13:51:05 +0200 Subject: [PATCH 3/6] Add gather function --- .../src/builder/spirv_asm.rs | 18 +++++++++ crates/spirv-std/src/image.rs | 37 ++++++++++++++++++- tests/ui/image/gather.rs | 21 +++++++++++ tests/ui/image/gather_err.rs | 18 +++++++++ tests/ui/image/gather_err.stderr | 30 +++++++++++++++ tests/ui/image/query/query_levels_err.stderr | 14 +++---- tests/ui/image/query/query_lod_err.stderr | 14 +++---- tests/ui/image/query/query_size_err.stderr | 16 ++++---- .../ui/image/query/query_size_lod_err.stderr | 14 +++---- 9 files changed, 151 insertions(+), 31 deletions(-) create mode 100644 tests/ui/image/gather.rs create mode 100644 tests/ui/image/gather_err.rs create mode 100644 tests/ui/image/gather_err.stderr diff --git a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs index 26bb368126..353a7e431b 100644 --- a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs +++ b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs @@ -1379,6 +1379,24 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { } match inst.class.opcode { + Op::ImageGather => { + let image_ty = match find_image_ty(self, inst) { + Some(ty) => ty, + None => return, + }; + if let SpirvType::Image { dim, .. } = image_ty { + match dim { + Dim::Dim2D | Dim::DimCube | Dim::DimRect => {} + bad => self + .struct_err(&format!( + "Op{}'s image has a dimension of {:?}", + inst.class.opname, bad + )) + .note("Allowed dimensions are 2D, Cube, and Rect") + .emit(), + } + } + } Op::ImageQueryLevels | Op::ImageQueryLod => { let image_ty = match find_image_ty(self, inst) { Some(ty) => ty, diff --git a/crates/spirv-std/src/image.rs b/crates/spirv-std/src/image.rs index 6f98e51c5c..7b796d6db4 100644 --- a/crates/spirv-std/src/image.rs +++ b/crates/spirv-std/src/image.rs @@ -136,6 +136,39 @@ impl< ACCESS_QUALIFIER, > { + /// Gathers the requested component from four texels. + #[crate::macros::gpu_only] + #[doc(alias = "OpImageGather")] + pub fn gather( + &self, + sampler: Sampler, + coordinate: impl ImageCoordinate, + component: u32, + ) -> V + where + F: Float, + V: Vector, + { + let mut result = V::default(); + unsafe { + asm! { + "%typeSampledImage = OpTypeSampledImage typeof*{this}", + "%image = OpLoad _ {this}", + "%sampler = OpLoad _ {sampler}", + "%coordinate = OpLoad _ {coordinate}", + "%sampledImage = OpSampledImage %typeSampledImage %image %sampler", + "%result = OpImageGather typeof*{result} %sampledImage %coordinate {component}", + "OpStore {result} %result", + result = in(reg) &mut result, + this = in(reg) self, + sampler = in(reg) &sampler, + coordinate = in(reg) &coordinate, + component = in(reg) component, + } + } + result + } + /// Sample texels at `coord` from the image using `sampler`. #[crate::macros::gpu_only] pub fn sample(&self, sampler: Sampler, coord: impl ImageCoordinate) -> V @@ -391,9 +424,9 @@ impl< ACCESS_QUALIFIER, > { - /// Fetch a single texel with a sampler set at compile time + /// Sample the image with a project coordinate #[crate::macros::gpu_only] - #[doc(alias = "OpImageFetch")] + #[doc(alias = "OpImageSampleProjImplicitLod")] pub fn sample_with_project_coordinate( &self, sampler: Sampler, diff --git a/tests/ui/image/gather.rs b/tests/ui/image/gather.rs new file mode 100644 index 0000000000..8f997097c3 --- /dev/null +++ b/tests/ui/image/gather.rs @@ -0,0 +1,21 @@ +// Test `OpImageGather` +// build-pass +// compile-flags: -Ctarget-feature=+SampledRect + +use spirv_std::{arch, Image, Sampler}; + +#[spirv(fragment)] +pub fn main( + #[spirv(descriptor_set = 0, binding = 0)] image2d: &Image!(2D, type=f32, sampled), + #[spirv(descriptor_set = 1, binding = 1)] rect: &Image!(rect, type=f32, sampled), + #[spirv(descriptor_set = 2, binding = 2)] cubemap: &Image!(cube, type=f32, sampled), + #[spirv(descriptor_set = 3, binding = 3)] sampler: &Sampler, + output: &mut glam::Vec4, +) { + let v2 = glam::Vec2::new(0.0, 1.0); + let v3 = glam::Vec3::new(0.0, 1.0, 0.5); + let r1: glam::Vec4 = image2d.gather(*sampler, v2, 0); + let r2: glam::Vec4 = rect.gather(*sampler, v2, 0); + let r3: glam::Vec4 = cubemap.gather(*sampler, v3, 0); + *output = r1 + r2 + r3; +} diff --git a/tests/ui/image/gather_err.rs b/tests/ui/image/gather_err.rs new file mode 100644 index 0000000000..5ec3b80656 --- /dev/null +++ b/tests/ui/image/gather_err.rs @@ -0,0 +1,18 @@ +// build-fail +// normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" +// compile-flags: -Ctarget-feature=+Sampled1D + +use spirv_std::{arch, Image, Sampler}; + +#[spirv(fragment)] +pub fn main( + #[spirv(descriptor_set = 0, binding = 0)] image1d: &Image!(1D, type=f32, sampled), + #[spirv(descriptor_set = 2, binding = 1)] image3d: &Image!(3D, type=f32, sampled), + #[spirv(descriptor_set = 3, binding = 3)] sampler: &Sampler, + output: &mut glam::Vec4, +) { + let v3 = glam::Vec3::new(0.0, 1.0, 0.5); + let r1: glam::Vec4 = image1d.gather(*sampler, 0.0, 0); + let r2: glam::Vec4 = image3d.gather(*sampler, v3, 0); + *output = r1 + r2; +} diff --git a/tests/ui/image/gather_err.stderr b/tests/ui/image/gather_err.stderr new file mode 100644 index 0000000000..60b5556163 --- /dev/null +++ b/tests/ui/image/gather_err.stderr @@ -0,0 +1,30 @@ +error: OpImageGather's image has a dimension of Dim1D + --> $SPIRV_STD_SRC/image.rs:154:13 + | +154 | / asm! { +155 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}", +156 | | "%image = OpLoad _ {this}", +157 | | "%sampler = OpLoad _ {sampler}", +... | +166 | | component = in(reg) component, +167 | | } + | |_____________^ + | + = note: Allowed dimensions are 2D, Cube, and Rect + +error: OpImageGather's image has a dimension of Dim3D + --> $SPIRV_STD_SRC/image.rs:154:13 + | +154 | / asm! { +155 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}", +156 | | "%image = OpLoad _ {this}", +157 | | "%sampler = OpLoad _ {sampler}", +... | +166 | | component = in(reg) component, +167 | | } + | |_____________^ + | + = note: Allowed dimensions are 2D, Cube, and Rect + +error: aborting due to 2 previous errors + diff --git a/tests/ui/image/query/query_levels_err.stderr b/tests/ui/image/query/query_levels_err.stderr index a520f86ca6..2d1d9362c7 100644 --- a/tests/ui/image/query/query_levels_err.stderr +++ b/tests/ui/image/query/query_levels_err.stderr @@ -1,12 +1,12 @@ error: OpImageQueryLevels's image has a dimension of DimRect - --> $SPIRV_STD_SRC/image.rs:796:13 + --> $SPIRV_STD_SRC/image.rs:829:13 | -796 | / asm! { -797 | | "%image = OpLoad _ {this}", -798 | | "{result} = OpImageQueryLevels typeof{result} %image", -799 | | this = in(reg) self, -800 | | result = out(reg) result, -801 | | } +829 | / asm! { +830 | | "%image = OpLoad _ {this}", +831 | | "{result} = OpImageQueryLevels typeof{result} %image", +832 | | this = in(reg) self, +833 | | result = out(reg) result, +834 | | } | |_____________^ | = note: Allowed dimensions are 1D, 2D, 3D, and Cube diff --git a/tests/ui/image/query/query_lod_err.stderr b/tests/ui/image/query/query_lod_err.stderr index 057d9139b0..7452b73c4e 100644 --- a/tests/ui/image/query/query_lod_err.stderr +++ b/tests/ui/image/query/query_lod_err.stderr @@ -1,13 +1,13 @@ error: OpImageQueryLod's image has a dimension of DimRect - --> $SPIRV_STD_SRC/image.rs:829:13 + --> $SPIRV_STD_SRC/image.rs:862:13 | -829 | / asm! { -830 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}", -831 | | "%image = OpLoad _ {this}", -832 | | "%sampler = OpLoad _ {sampler}", +862 | / asm! { +863 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}", +864 | | "%image = OpLoad _ {this}", +865 | | "%sampler = OpLoad _ {sampler}", ... | -840 | | coord = in(reg) &coord -841 | | } +873 | | coord = in(reg) &coord +874 | | } | |_____________^ | = note: Allowed dimensions are 1D, 2D, 3D, and Cube diff --git a/tests/ui/image/query/query_size_err.stderr b/tests/ui/image/query/query_size_err.stderr index 541414bc12..d6a330c6d3 100644 --- a/tests/ui/image/query/query_size_err.stderr +++ b/tests/ui/image/query/query_size_err.stderr @@ -1,13 +1,13 @@ error: OpImageQuerySize is invalid for this image type - --> $SPIRV_STD_SRC/image.rs:858:13 + --> $SPIRV_STD_SRC/image.rs:891:13 | -858 | / asm! { -859 | | "%image = OpLoad _ {this}", -860 | | "%result = OpImageQuerySize typeof*{result} %image", -861 | | "OpStore {result} %result", -862 | | this = in(reg) self, -863 | | result = in(reg) &mut result, -864 | | } +891 | / asm! { +892 | | "%image = OpLoad _ {this}", +893 | | "%result = OpImageQuerySize typeof*{result} %image", +894 | | "OpStore {result} %result", +895 | | this = in(reg) self, +896 | | result = in(reg) &mut result, +897 | | } | |_____________^ | = note: allowed dimensions are 1D, 2D, 3D, Buffer, Rect, or Cube. if dimension is 1D, 2D, 3D, or Cube, it must have either multisampled be true, *or* sampled of Unknown or No diff --git a/tests/ui/image/query/query_size_lod_err.stderr b/tests/ui/image/query/query_size_lod_err.stderr index c5dbe23ad1..ee7630bf97 100644 --- a/tests/ui/image/query/query_size_lod_err.stderr +++ b/tests/ui/image/query/query_size_lod_err.stderr @@ -1,13 +1,13 @@ error: OpImageQuerySizeLod is invalid for this image type - --> $SPIRV_STD_SRC/image.rs:904:13 + --> $SPIRV_STD_SRC/image.rs:937:13 | -904 | / asm! { -905 | | "%image = OpLoad _ {this}", -906 | | "%result = OpImageQuerySizeLod typeof*{result} %image {lod}", -907 | | "OpStore {result} %result", +937 | / asm! { +938 | | "%image = OpLoad _ {this}", +939 | | "%result = OpImageQuerySizeLod typeof*{result} %image {lod}", +940 | | "OpStore {result} %result", ... | -910 | | result = in(reg) &mut result, -911 | | } +943 | | result = in(reg) &mut result, +944 | | } | |_____________^ | = note: The image's dimension must be 1D, 2D, 3D, or Cube. Multisampled must be false. From fcd51e59808f1e52560ddcf746768f2eed75bd14 Mon Sep 17 00:00:00 2001 From: khyperia Date: Thu, 5 Aug 2021 14:05:15 +0200 Subject: [PATCH 4/6] Update spirv-tools CI was failing on "Capability SampledRect is not allowed by Vulkan 1.1 specification (or requires extension)", except locally it was fine, and I have more up to date spirv-tools than CI, so try bumping the CI version to see if it's just an out-of-date spirv-val --- .github/workflows/ci.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3634992b0e..ca5d33e771 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -22,7 +22,7 @@ jobs: target: aarch64-linux-android runs-on: ${{ matrix.os }} env: - spirv_tools_version: "20200928" + spirv_tools_version: "20210805" RUSTUP_UNPACK_RAM: "26214400" RUSTUP_IO_THREADS: "1" steps: @@ -34,7 +34,7 @@ jobs: run: | sudo apt install libwayland-cursor0 libxkbcommon-dev libwayland-dev mkdir "${HOME}/spirv-tools" - curl -fL https://storage.googleapis.com/spirv-tools/artifacts/prod/graphics_shader_compiler/spirv-tools/linux-clang-release/continuous/1409/20210313-175801/install.tgz | tar -xz -C "${HOME}/spirv-tools" + curl -fL https://storage.googleapis.com/spirv-tools/artifacts/prod/graphics_shader_compiler/spirv-tools/linux-clang-release/continuous/1530/20210805-040049/install.tgz | tar -xz -C "${HOME}/spirv-tools" echo "${HOME}/spirv-tools/install/bin" >> $GITHUB_PATH - if: ${{ runner.os == 'macOS' }} name: Mac - Install spirv-tools @@ -47,7 +47,7 @@ jobs: run: | tmparch=$(mktemp) mkdir "${HOME}/spirv-tools" - curl -fL -o "$tmparch" https://storage.googleapis.com/spirv-tools/artifacts/prod/graphics_shader_compiler/spirv-tools/windows-msvc-2017-release/continuous/1391/20210313-183536/install.zip + curl -fL -o "$tmparch" https://storage.googleapis.com/spirv-tools/artifacts/prod/graphics_shader_compiler/spirv-tools/windows-msvc-2017-release/continuous/1517/20210805-040116/install.zip unzip "$tmparch" -d "${HOME}/spirv-tools" - if: ${{ runner.os == 'Windows' }} # Runs separately to add spir-v tools to Powershell's Path. From 91545714068d9ed17b3667745625aaef0f76d990 Mon Sep 17 00:00:00 2001 From: khyperia Date: Thu, 5 Aug 2021 14:48:42 +0200 Subject: [PATCH 5/6] Fix gather() in vulkan --- crates/spirv-std/src/image.rs | 2 ++ tests/ui/image/gather.rs | 24 ++++++++++++---- tests/ui/image/gather_err.stderr | 28 +++++++++---------- tests/ui/image/query/query_levels_err.stderr | 14 +++++----- tests/ui/image/query/query_lod_err.stderr | 14 +++++----- tests/ui/image/query/query_size_err.stderr | 16 +++++------ .../ui/image/query/query_size_lod_err.stderr | 14 +++++----- 7 files changed, 64 insertions(+), 48 deletions(-) diff --git a/crates/spirv-std/src/image.rs b/crates/spirv-std/src/image.rs index 7b796d6db4..9ff63ede4d 100644 --- a/crates/spirv-std/src/image.rs +++ b/crates/spirv-std/src/image.rs @@ -136,9 +136,11 @@ impl< ACCESS_QUALIFIER, > { + // Note: #[inline] is needed because in vulkan, the component must be a constant expression. /// Gathers the requested component from four texels. #[crate::macros::gpu_only] #[doc(alias = "OpImageGather")] + #[inline] pub fn gather( &self, sampler: Sampler, diff --git a/tests/ui/image/gather.rs b/tests/ui/image/gather.rs index 8f997097c3..dd2bf88a3e 100644 --- a/tests/ui/image/gather.rs +++ b/tests/ui/image/gather.rs @@ -1,13 +1,11 @@ // Test `OpImageGather` // build-pass -// compile-flags: -Ctarget-feature=+SampledRect use spirv_std::{arch, Image, Sampler}; #[spirv(fragment)] pub fn main( #[spirv(descriptor_set = 0, binding = 0)] image2d: &Image!(2D, type=f32, sampled), - #[spirv(descriptor_set = 1, binding = 1)] rect: &Image!(rect, type=f32, sampled), #[spirv(descriptor_set = 2, binding = 2)] cubemap: &Image!(cube, type=f32, sampled), #[spirv(descriptor_set = 3, binding = 3)] sampler: &Sampler, output: &mut glam::Vec4, @@ -15,7 +13,23 @@ pub fn main( let v2 = glam::Vec2::new(0.0, 1.0); let v3 = glam::Vec3::new(0.0, 1.0, 0.5); let r1: glam::Vec4 = image2d.gather(*sampler, v2, 0); - let r2: glam::Vec4 = rect.gather(*sampler, v2, 0); - let r3: glam::Vec4 = cubemap.gather(*sampler, v3, 0); - *output = r1 + r2 + r3; + let r2: glam::Vec4 = cubemap.gather(*sampler, v3, 0); + *output = r1 + r2; +} + +#[cfg(not(any( + target_env = "vulkan1.0", + target_env = "vulkan1.1", + target_env = "vulkan1.2" +)))] +#[spirv(fragment)] +pub fn main_rect( + #[spirv(descriptor_set = 1, binding = 1)] rect: &Image!(rect, type=f32, sampled), + #[spirv(descriptor_set = 3, binding = 3)] sampler: &Sampler, + output: &mut glam::Vec4, +) { + // Must be asm! and not -Ctarget-feature=+SampledRect due to being in cfg + unsafe{asm!("OpCapability SampledRect")}; + let v2 = glam::Vec2::new(0.0, 1.0); + *output = rect.gather(*sampler, v2, 0); } diff --git a/tests/ui/image/gather_err.stderr b/tests/ui/image/gather_err.stderr index 60b5556163..29ce124c1b 100644 --- a/tests/ui/image/gather_err.stderr +++ b/tests/ui/image/gather_err.stderr @@ -1,27 +1,27 @@ error: OpImageGather's image has a dimension of Dim1D - --> $SPIRV_STD_SRC/image.rs:154:13 + --> $SPIRV_STD_SRC/image.rs:156:13 | -154 | / asm! { -155 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}", -156 | | "%image = OpLoad _ {this}", -157 | | "%sampler = OpLoad _ {sampler}", +156 | / asm! { +157 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}", +158 | | "%image = OpLoad _ {this}", +159 | | "%sampler = OpLoad _ {sampler}", ... | -166 | | component = in(reg) component, -167 | | } +168 | | component = in(reg) component, +169 | | } | |_____________^ | = note: Allowed dimensions are 2D, Cube, and Rect error: OpImageGather's image has a dimension of Dim3D - --> $SPIRV_STD_SRC/image.rs:154:13 + --> $SPIRV_STD_SRC/image.rs:156:13 | -154 | / asm! { -155 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}", -156 | | "%image = OpLoad _ {this}", -157 | | "%sampler = OpLoad _ {sampler}", +156 | / asm! { +157 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}", +158 | | "%image = OpLoad _ {this}", +159 | | "%sampler = OpLoad _ {sampler}", ... | -166 | | component = in(reg) component, -167 | | } +168 | | component = in(reg) component, +169 | | } | |_____________^ | = note: Allowed dimensions are 2D, Cube, and Rect diff --git a/tests/ui/image/query/query_levels_err.stderr b/tests/ui/image/query/query_levels_err.stderr index 2d1d9362c7..d76e1bdd75 100644 --- a/tests/ui/image/query/query_levels_err.stderr +++ b/tests/ui/image/query/query_levels_err.stderr @@ -1,12 +1,12 @@ error: OpImageQueryLevels's image has a dimension of DimRect - --> $SPIRV_STD_SRC/image.rs:829:13 + --> $SPIRV_STD_SRC/image.rs:831:13 | -829 | / asm! { -830 | | "%image = OpLoad _ {this}", -831 | | "{result} = OpImageQueryLevels typeof{result} %image", -832 | | this = in(reg) self, -833 | | result = out(reg) result, -834 | | } +831 | / asm! { +832 | | "%image = OpLoad _ {this}", +833 | | "{result} = OpImageQueryLevels typeof{result} %image", +834 | | this = in(reg) self, +835 | | result = out(reg) result, +836 | | } | |_____________^ | = note: Allowed dimensions are 1D, 2D, 3D, and Cube diff --git a/tests/ui/image/query/query_lod_err.stderr b/tests/ui/image/query/query_lod_err.stderr index 7452b73c4e..b11daaacb4 100644 --- a/tests/ui/image/query/query_lod_err.stderr +++ b/tests/ui/image/query/query_lod_err.stderr @@ -1,13 +1,13 @@ error: OpImageQueryLod's image has a dimension of DimRect - --> $SPIRV_STD_SRC/image.rs:862:13 + --> $SPIRV_STD_SRC/image.rs:864:13 | -862 | / asm! { -863 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}", -864 | | "%image = OpLoad _ {this}", -865 | | "%sampler = OpLoad _ {sampler}", +864 | / asm! { +865 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}", +866 | | "%image = OpLoad _ {this}", +867 | | "%sampler = OpLoad _ {sampler}", ... | -873 | | coord = in(reg) &coord -874 | | } +875 | | coord = in(reg) &coord +876 | | } | |_____________^ | = note: Allowed dimensions are 1D, 2D, 3D, and Cube diff --git a/tests/ui/image/query/query_size_err.stderr b/tests/ui/image/query/query_size_err.stderr index d6a330c6d3..6fc68173b9 100644 --- a/tests/ui/image/query/query_size_err.stderr +++ b/tests/ui/image/query/query_size_err.stderr @@ -1,13 +1,13 @@ error: OpImageQuerySize is invalid for this image type - --> $SPIRV_STD_SRC/image.rs:891:13 + --> $SPIRV_STD_SRC/image.rs:893:13 | -891 | / asm! { -892 | | "%image = OpLoad _ {this}", -893 | | "%result = OpImageQuerySize typeof*{result} %image", -894 | | "OpStore {result} %result", -895 | | this = in(reg) self, -896 | | result = in(reg) &mut result, -897 | | } +893 | / asm! { +894 | | "%image = OpLoad _ {this}", +895 | | "%result = OpImageQuerySize typeof*{result} %image", +896 | | "OpStore {result} %result", +897 | | this = in(reg) self, +898 | | result = in(reg) &mut result, +899 | | } | |_____________^ | = note: allowed dimensions are 1D, 2D, 3D, Buffer, Rect, or Cube. if dimension is 1D, 2D, 3D, or Cube, it must have either multisampled be true, *or* sampled of Unknown or No diff --git a/tests/ui/image/query/query_size_lod_err.stderr b/tests/ui/image/query/query_size_lod_err.stderr index ee7630bf97..215f1d45fb 100644 --- a/tests/ui/image/query/query_size_lod_err.stderr +++ b/tests/ui/image/query/query_size_lod_err.stderr @@ -1,13 +1,13 @@ error: OpImageQuerySizeLod is invalid for this image type - --> $SPIRV_STD_SRC/image.rs:937:13 + --> $SPIRV_STD_SRC/image.rs:939:13 | -937 | / asm! { -938 | | "%image = OpLoad _ {this}", -939 | | "%result = OpImageQuerySizeLod typeof*{result} %image {lod}", -940 | | "OpStore {result} %result", +939 | / asm! { +940 | | "%image = OpLoad _ {this}", +941 | | "%result = OpImageQuerySizeLod typeof*{result} %image {lod}", +942 | | "OpStore {result} %result", ... | -943 | | result = in(reg) &mut result, -944 | | } +945 | | result = in(reg) &mut result, +946 | | } | |_____________^ | = note: The image's dimension must be 1D, 2D, 3D, or Cube. Multisampled must be false. From af76d5873bb82c9d55b34c2bbbd63e9d8e2fb14e Mon Sep 17 00:00:00 2001 From: khyperia Date: Fri, 6 Aug 2021 10:58:17 +0200 Subject: [PATCH 6/6] Convert compiler valication into marker traits --- .../src/builder/spirv_asm.rs | 146 +---- crates/spirv-std/src/image.rs | 566 +++++++++++++++++- tests/ui/image/gather.rs | 2 +- tests/ui/image/gather_err.stderr | 47 +- tests/ui/image/query/query_levels_err.stderr | 24 +- tests/ui/image/query/query_lod_err.stderr | 25 +- tests/ui/image/query/query_size_err.stderr | 27 +- .../ui/image/query/query_size_lod_err.stderr | 26 +- 8 files changed, 613 insertions(+), 250 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs index 353a7e431b..5a84dd7919 100644 --- a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs +++ b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs @@ -5,7 +5,7 @@ use crate::spirv_type::SpirvType; use rspirv::dr; use rspirv::grammar::{LogicalOperand, OperandKind, OperandQuantifier}; use rspirv::spirv::{ - Dim, FPFastMathMode, FragmentShadingRate, FunctionControl, ImageOperands, KernelProfilingInfo, + FPFastMathMode, FragmentShadingRate, FunctionControl, ImageOperands, KernelProfilingInfo, LoopControl, MemoryAccess, MemorySemantics, Op, RayFlags, SelectionControl, StorageClass, Word, }; use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; @@ -333,7 +333,6 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { return; } _ => { - self.validate_instruction(&inst); self.emit() .insert_into_block(dr::InsertPoint::End, inst) .unwrap(); @@ -1314,149 +1313,6 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { } true } - - pub fn validate_instruction(&mut self, inst: &dr::Instruction) { - fn find_image_ty<'cx, 'tcx>( - builder: &mut Builder<'cx, 'tcx>, - inst: &dr::Instruction, - ) -> Option { - // Assumes the image parameter is the first operand - let image_obj = inst.operands[0].unwrap_id_ref(); - let emit = builder.emit(); - // Assumes the image's value definition is in the current block - let block = &emit.module_ref().functions[emit.selected_function().unwrap()].blocks - [emit.selected_block().unwrap()]; - // Loop through the block to find the defining instruction - let defining_inst = match block - .instructions - .iter() - .find(|inst| inst.result_id == Some(image_obj)) - { - Some(defining_inst) => defining_inst, - None => { - // Something has gone wrong. All the asm! blocks using these instructions - // should produce the image value in their own basic blocks (usually with - // an OpLoad), so there's probably some typo somewhere with an error - // already emitted, so just skip validation. If there truly is something - // bad going on, spirv-val will catch it. - return None; - } - }; - match builder.lookup_type(defining_inst.result_type.unwrap()) { - SpirvType::SampledImage { image_type } => Some(builder.lookup_type(image_type)), - ty => Some(ty), - } - } - - fn is_valid_query_size(ty: &SpirvType) -> bool { - match *ty { - SpirvType::Image { - dim, - multisampled, - sampled, - .. - } => match dim { - Dim::Dim1D | Dim::Dim2D | Dim::Dim3D | Dim::DimCube => { - multisampled == 1 || sampled == 0 || sampled == 2 - } - Dim::DimBuffer | Dim::DimRect => true, - Dim::DimSubpassData => false, - }, - _ => true, - } - } - - fn is_valid_query_size_lod(ty: &SpirvType) -> bool { - match *ty { - SpirvType::Image { - dim, multisampled, .. - } => match dim { - Dim::Dim1D | Dim::Dim2D | Dim::Dim3D | Dim::DimCube => multisampled == 0, - _ => false, - }, - _ => true, - } - } - - match inst.class.opcode { - Op::ImageGather => { - let image_ty = match find_image_ty(self, inst) { - Some(ty) => ty, - None => return, - }; - if let SpirvType::Image { dim, .. } = image_ty { - match dim { - Dim::Dim2D | Dim::DimCube | Dim::DimRect => {} - bad => self - .struct_err(&format!( - "Op{}'s image has a dimension of {:?}", - inst.class.opname, bad - )) - .note("Allowed dimensions are 2D, Cube, and Rect") - .emit(), - } - } - } - Op::ImageQueryLevels | Op::ImageQueryLod => { - let image_ty = match find_image_ty(self, inst) { - Some(ty) => ty, - None => return, - }; - if let SpirvType::Image { dim, .. } = image_ty { - match dim { - Dim::Dim1D | Dim::Dim2D | Dim::Dim3D | Dim::DimCube => {} - bad => self - .struct_err(&format!( - "Op{}'s image has a dimension of {:?}", - inst.class.opname, bad - )) - .note("Allowed dimensions are 1D, 2D, 3D, and Cube") - .emit(), - } - } - // If the type isn't an image, something has gone wrong. The functions in image.rs - // shouldn't allow it, so the user is doing something weird. Let spirv-val handle - // the error later on. - } - Op::ImageQuerySize => { - let image_ty = match find_image_ty(self, inst) { - Some(ty) => ty, - None => return, - }; - if !is_valid_query_size(&image_ty) { - let mut err = - self.struct_err("OpImageQuerySize is invalid for this image type"); - err.note( - "allowed dimensions are 1D, 2D, 3D, Buffer, Rect, or Cube. \ - if dimension is 1D, 2D, 3D, or Cube, it must have either \ - multisampled be true, *or* sampled of Unknown or No", - ); - if is_valid_query_size_lod(&image_ty) { - err.note("query_size_lod is valid for this image, did you mean to use it instead?"); - } - err.emit(); - } - } - Op::ImageQuerySizeLod => { - let image_ty = match find_image_ty(self, inst) { - Some(ty) => ty, - None => return, - }; - if !is_valid_query_size_lod(&image_ty) { - let mut err = - self.struct_err("OpImageQuerySizeLod is invalid for this image type"); - err.note("The image's dimension must be 1D, 2D, 3D, or Cube. Multisampled must be false."); - if is_valid_query_size(&image_ty) { - err.note( - "query_size is valid for this image, did you mean to use it instead?", - ); - } - err.emit(); - } - } - _ => {} - } - } } pub const IMAGE_OPERANDS: &[(&str, ImageOperands)] = &[ diff --git a/crates/spirv-std/src/image.rs b/crates/spirv-std/src/image.rs index 9ff63ede4d..9e38533a30 100644 --- a/crates/spirv-std/src/image.rs +++ b/crates/spirv-std/src/image.rs @@ -148,6 +148,7 @@ impl< component: u32, ) -> V where + Self: HasGather, F: Float, V: Vector, { @@ -818,14 +819,12 @@ impl< > Image { /// Query the number of mipmap levels. - /// - /// Note: Const generics aren't able to reason about the constraints on this function (yet), - /// and so are enforced by the compiler. The constraints are: - /// - /// The image's dimension must be 1D, 2D, 3D, or Cube. #[crate::macros::gpu_only] #[doc(alias = "OpImageQueryLevels")] - pub fn query_levels(&self) -> u32 { + pub fn query_levels(&self) -> u32 + where + Self: HasQueryLevels, + { let result: u32; unsafe { asm! { @@ -842,18 +841,16 @@ impl< /// Coordinate using an implicit level of detail. The first component of the result contains /// the mipmap array layer. The second component of the result contains the implicit level of /// detail relative to the base level. - /// - /// Note: Const generics aren't able to reason about the constraints on this function (yet), - /// and so are enforced by the compiler. The constraints are: - /// - /// The image's dimension must be 1D, 2D, 3D, or Cube. #[crate::macros::gpu_only] #[doc(alias = "OpImageQueryLod")] pub fn query_lod>( &self, sampler: Sampler, coord: impl ImageCoordinate, - ) -> V { + ) -> V + where + Self: HasQueryLevels, + { // Note: Arrayed::False isn't a typo in the ImageCoordinate, the spec states: // Coordinate must be a scalar or vector of floating-point type or integer type. It // contains (u[, v] ... ) as needed by the definition of Sampled Image, **not including any @@ -879,15 +876,12 @@ impl< } /// Query the dimensions of Image, with no level of detail. - /// - /// Note: Const generics aren't able to reason about the constraints on this function (yet), - /// and so are enforced by the compiler. The constraints are: - /// - /// The image's dimension must be 1D, 2D, 3D, Buffer, Rect, or Cube. If dimension is 1D, 2D, - /// 3D, or Cube, it must have *either* multisampled be true, *or* sampled of Unknown or No. #[crate::macros::gpu_only] #[doc(alias = "OpImageQuerySize")] - pub fn query_size + Default>(&self) -> Size { + pub fn query_size + Default>(&self) -> Size + where + Self: HasQuerySize, + { let mut result: Size = Default::default(); unsafe { asm! { @@ -923,17 +917,15 @@ impl< > { /// Query the dimensions of Image, with no level of detail. - /// - /// Note: Const generics aren't able to reason about the constraints on this function (yet), - /// and so are enforced by the compiler. The constraints are: - /// - /// The image's dimension must be 1D, 2D, 3D, or Cube. Multisampled must be false. #[crate::macros::gpu_only] #[doc(alias = "OpImageQuerySizeLod")] pub fn query_size_lod + Default>( &self, lod: u32, - ) -> Size { + ) -> Size + where + Self: HasQuerySizeLod, + { let mut result: Size = Default::default(); unsafe { asm! { @@ -1042,3 +1034,527 @@ impl< result } } + +/// This is a marker trait to represent the constraints on `OpImageGather` too complex to be +/// represented by const generics. Specifically: +/// +/// "Its `OpTypeImage` must have a Dim of 2D, Cube, or Rect. The MS operand of the underlying +/// `OpTypeImage` must be 0." +pub trait HasGather {} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasGather + for Image< + SampledType, + { Dimensionality::TwoD }, + DEPTH, + ARRAYED, + { Multisampled::False }, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasGather + for Image< + SampledType, + { Dimensionality::Rect }, + DEPTH, + ARRAYED, + { Multisampled::False }, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasGather + for Image< + SampledType, + { Dimensionality::Cube }, + DEPTH, + ARRAYED, + { Multisampled::False }, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} + +/// This is a marker trait to represent the constraints on `OpImageQueryLevels` and +/// `OpImageQueryLod` too complex to be represented by const generics. Specifically: +/// +/// "Its Dim operand must be one of 1D, 2D, 3D, or Cube." +pub trait HasQueryLevels {} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const MULTISAMPLED: Multisampled, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasQueryLevels + for Image< + SampledType, + { Dimensionality::OneD }, + DEPTH, + ARRAYED, + MULTISAMPLED, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const MULTISAMPLED: Multisampled, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasQueryLevels + for Image< + SampledType, + { Dimensionality::TwoD }, + DEPTH, + ARRAYED, + MULTISAMPLED, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const MULTISAMPLED: Multisampled, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasQueryLevels + for Image< + SampledType, + { Dimensionality::ThreeD }, + DEPTH, + ARRAYED, + MULTISAMPLED, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const MULTISAMPLED: Multisampled, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasQueryLevels + for Image< + SampledType, + { Dimensionality::Cube }, + DEPTH, + ARRAYED, + MULTISAMPLED, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} + +/// This is a marker trait to represent the constraints on `OpImageQuerySize` too complex to be +/// represented by const generics. Specifically: +/// +/// "Its Dim operand must be 1D, 2D, 3D, Cube, Rect, or Buffer. Additionally, if its Dim is 1D, 2D, +/// 3D, or Cube, it must also have either an MS of 1 or a Sampled of 0 or 2." +pub trait HasQuerySize {} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasQuerySize + for Image< + SampledType, + { Dimensionality::OneD }, + DEPTH, + ARRAYED, + { Multisampled::True }, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const ACCESS_QUALIFIER: Option, + > HasQuerySize + for Image< + SampledType, + { Dimensionality::OneD }, + DEPTH, + ARRAYED, + { Multisampled::False }, + { Sampled::Unknown }, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const ACCESS_QUALIFIER: Option, + > HasQuerySize + for Image< + SampledType, + { Dimensionality::OneD }, + DEPTH, + ARRAYED, + { Multisampled::False }, + { Sampled::No }, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasQuerySize + for Image< + SampledType, + { Dimensionality::TwoD }, + DEPTH, + ARRAYED, + { Multisampled::True }, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const ACCESS_QUALIFIER: Option, + > HasQuerySize + for Image< + SampledType, + { Dimensionality::TwoD }, + DEPTH, + ARRAYED, + { Multisampled::False }, + { Sampled::Unknown }, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const ACCESS_QUALIFIER: Option, + > HasQuerySize + for Image< + SampledType, + { Dimensionality::TwoD }, + DEPTH, + ARRAYED, + { Multisampled::False }, + { Sampled::No }, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasQuerySize + for Image< + SampledType, + { Dimensionality::ThreeD }, + DEPTH, + ARRAYED, + { Multisampled::True }, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const ACCESS_QUALIFIER: Option, + > HasQuerySize + for Image< + SampledType, + { Dimensionality::ThreeD }, + DEPTH, + ARRAYED, + { Multisampled::False }, + { Sampled::Unknown }, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const ACCESS_QUALIFIER: Option, + > HasQuerySize + for Image< + SampledType, + { Dimensionality::ThreeD }, + DEPTH, + ARRAYED, + { Multisampled::False }, + { Sampled::No }, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasQuerySize + for Image< + SampledType, + { Dimensionality::Cube }, + DEPTH, + ARRAYED, + { Multisampled::True }, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const ACCESS_QUALIFIER: Option, + > HasQuerySize + for Image< + SampledType, + { Dimensionality::Cube }, + DEPTH, + ARRAYED, + { Multisampled::False }, + { Sampled::Unknown }, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const ACCESS_QUALIFIER: Option, + > HasQuerySize + for Image< + SampledType, + { Dimensionality::Cube }, + DEPTH, + ARRAYED, + { Multisampled::False }, + { Sampled::No }, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const MULTISAMPLED: Multisampled, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasQuerySize + for Image< + SampledType, + { Dimensionality::Rect }, + DEPTH, + ARRAYED, + MULTISAMPLED, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const MULTISAMPLED: Multisampled, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasQuerySize + for Image< + SampledType, + { Dimensionality::Buffer }, + DEPTH, + ARRAYED, + MULTISAMPLED, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} + +/// This is a marker trait to represent the constraints on `OpImageQuerySizeLod` too complex to be +/// represented by const generics. Specifically: +/// +/// "Its Dim operand must be one of 1D, 2D, 3D, or Cube, and its MS must be 0." +pub trait HasQuerySizeLod {} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasQuerySizeLod + for Image< + SampledType, + { Dimensionality::OneD }, + DEPTH, + ARRAYED, + { Multisampled::False }, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasQuerySizeLod + for Image< + SampledType, + { Dimensionality::TwoD }, + DEPTH, + ARRAYED, + { Multisampled::False }, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasQuerySizeLod + for Image< + SampledType, + { Dimensionality::ThreeD }, + DEPTH, + ARRAYED, + { Multisampled::False }, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} +impl< + SampledType: SampleType, + const DEPTH: ImageDepth, + const FORMAT: ImageFormat, + const ARRAYED: Arrayed, + const SAMPLED: Sampled, + const ACCESS_QUALIFIER: Option, + > HasQuerySizeLod + for Image< + SampledType, + { Dimensionality::Cube }, + DEPTH, + ARRAYED, + { Multisampled::False }, + SAMPLED, + FORMAT, + ACCESS_QUALIFIER, + > +{ +} diff --git a/tests/ui/image/gather.rs b/tests/ui/image/gather.rs index dd2bf88a3e..02a82446b8 100644 --- a/tests/ui/image/gather.rs +++ b/tests/ui/image/gather.rs @@ -29,7 +29,7 @@ pub fn main_rect( output: &mut glam::Vec4, ) { // Must be asm! and not -Ctarget-feature=+SampledRect due to being in cfg - unsafe{asm!("OpCapability SampledRect")}; + unsafe { asm!("OpCapability SampledRect") }; let v2 = glam::Vec2::new(0.0, 1.0); *output = rect.gather(*sampler, v2, 0); } diff --git a/tests/ui/image/gather_err.stderr b/tests/ui/image/gather_err.stderr index 29ce124c1b..14d1ca1f53 100644 --- a/tests/ui/image/gather_err.stderr +++ b/tests/ui/image/gather_err.stderr @@ -1,30 +1,25 @@ -error: OpImageGather's image has a dimension of Dim1D - --> $SPIRV_STD_SRC/image.rs:156:13 - | -156 | / asm! { -157 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}", -158 | | "%image = OpLoad _ {this}", -159 | | "%sampler = OpLoad _ {sampler}", -... | -168 | | component = in(reg) component, -169 | | } - | |_____________^ - | - = note: Allowed dimensions are 2D, Cube, and Rect +error[E0277]: the trait bound `Image::None>: HasGather` is not satisfied + --> $DIR/gather_err.rs:15:34 + | +15 | let r1: glam::Vec4 = image1d.gather(*sampler, 0.0, 0); + | ^^^^^^ the trait `HasGather` is not implemented for `Image::None>` + | + = help: the following implementations were found: + as HasGather> + as HasGather> + as HasGather> -error: OpImageGather's image has a dimension of Dim3D - --> $SPIRV_STD_SRC/image.rs:156:13 - | -156 | / asm! { -157 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}", -158 | | "%image = OpLoad _ {this}", -159 | | "%sampler = OpLoad _ {sampler}", -... | -168 | | component = in(reg) component, -169 | | } - | |_____________^ - | - = note: Allowed dimensions are 2D, Cube, and Rect +error[E0277]: the trait bound `Image::None>: HasGather` is not satisfied + --> $DIR/gather_err.rs:16:34 + | +16 | let r2: glam::Vec4 = image3d.gather(*sampler, v3, 0); + | ^^^^^^ the trait `HasGather` is not implemented for `Image::None>` + | + = help: the following implementations were found: + as HasGather> + as HasGather> + as HasGather> error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/image/query/query_levels_err.stderr b/tests/ui/image/query/query_levels_err.stderr index d76e1bdd75..56df54881c 100644 --- a/tests/ui/image/query/query_levels_err.stderr +++ b/tests/ui/image/query/query_levels_err.stderr @@ -1,15 +1,15 @@ -error: OpImageQueryLevels's image has a dimension of DimRect - --> $SPIRV_STD_SRC/image.rs:831:13 - | -831 | / asm! { -832 | | "%image = OpLoad _ {this}", -833 | | "{result} = OpImageQueryLevels typeof{result} %image", -834 | | this = in(reg) self, -835 | | result = out(reg) result, -836 | | } - | |_____________^ - | - = note: Allowed dimensions are 1D, 2D, 3D, and Cube +error[E0277]: the trait bound `Image::None>: HasQueryLevels` is not satisfied + --> $DIR/query_levels_err.rs:12:21 + | +12 | *output = image.query_levels(); + | ^^^^^^^^^^^^ the trait `HasQueryLevels` is not implemented for `Image::None>` + | + = help: the following implementations were found: + as HasQueryLevels> + as HasQueryLevels> + as HasQueryLevels> + as HasQueryLevels> error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/image/query/query_lod_err.stderr b/tests/ui/image/query/query_lod_err.stderr index b11daaacb4..f8f0bd3520 100644 --- a/tests/ui/image/query/query_lod_err.stderr +++ b/tests/ui/image/query/query_lod_err.stderr @@ -1,16 +1,15 @@ -error: OpImageQueryLod's image has a dimension of DimRect - --> $SPIRV_STD_SRC/image.rs:864:13 - | -864 | / asm! { -865 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}", -866 | | "%image = OpLoad _ {this}", -867 | | "%sampler = OpLoad _ {sampler}", -... | -875 | | coord = in(reg) &coord -876 | | } - | |_____________^ - | - = note: Allowed dimensions are 1D, 2D, 3D, and Cube +error[E0277]: the trait bound `Image::None>: HasQueryLevels` is not satisfied + --> $DIR/query_lod_err.rs:13:21 + | +13 | *output = image.query_lod(*sampler, glam::Vec2::new(0.0, 1.0)); + | ^^^^^^^^^ the trait `HasQueryLevels` is not implemented for `Image::None>` + | + = help: the following implementations were found: + as HasQueryLevels> + as HasQueryLevels> + as HasQueryLevels> + as HasQueryLevels> error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/image/query/query_size_err.stderr b/tests/ui/image/query/query_size_err.stderr index 6fc68173b9..36ca234d0d 100644 --- a/tests/ui/image/query/query_size_err.stderr +++ b/tests/ui/image/query/query_size_err.stderr @@ -1,17 +1,16 @@ -error: OpImageQuerySize is invalid for this image type - --> $SPIRV_STD_SRC/image.rs:893:13 - | -893 | / asm! { -894 | | "%image = OpLoad _ {this}", -895 | | "%result = OpImageQuerySize typeof*{result} %image", -896 | | "OpStore {result} %result", -897 | | this = in(reg) self, -898 | | result = in(reg) &mut result, -899 | | } - | |_____________^ - | - = note: allowed dimensions are 1D, 2D, 3D, Buffer, Rect, or Cube. if dimension is 1D, 2D, 3D, or Cube, it must have either multisampled be true, *or* sampled of Unknown or No - = note: query_size_lod is valid for this image, did you mean to use it instead? +error[E0277]: the trait bound `Image::None>: HasQuerySize` is not satisfied + --> $DIR/query_size_err.rs:12:21 + | +12 | *output = image.query_size(); + | ^^^^^^^^^^ the trait `HasQuerySize` is not implemented for `Image::None>` + | + = help: the following implementations were found: + as HasQuerySize> + as HasQuerySize> + as HasQuerySize> + as HasQuerySize> + and 10 others error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/image/query/query_size_lod_err.stderr b/tests/ui/image/query/query_size_lod_err.stderr index 215f1d45fb..64a8883e71 100644 --- a/tests/ui/image/query/query_size_lod_err.stderr +++ b/tests/ui/image/query/query_size_lod_err.stderr @@ -1,17 +1,15 @@ -error: OpImageQuerySizeLod is invalid for this image type - --> $SPIRV_STD_SRC/image.rs:939:13 - | -939 | / asm! { -940 | | "%image = OpLoad _ {this}", -941 | | "%result = OpImageQuerySizeLod typeof*{result} %image {lod}", -942 | | "OpStore {result} %result", -... | -945 | | result = in(reg) &mut result, -946 | | } - | |_____________^ - | - = note: The image's dimension must be 1D, 2D, 3D, or Cube. Multisampled must be false. - = note: query_size is valid for this image, did you mean to use it instead? +error[E0277]: the trait bound `Image::None>: HasQuerySizeLod` is not satisfied + --> $DIR/query_size_lod_err.rs:12:21 + | +12 | *output = image.query_size_lod(0); + | ^^^^^^^^^^^^^^ the trait `HasQuerySizeLod` is not implemented for `Image::None>` + | + = help: the following implementations were found: + as HasQuerySizeLod> + as HasQuerySizeLod> + as HasQuerySizeLod> + as HasQuerySizeLod> error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`.