From ca6a64cb43a74943ee1a648a886959121b2d1dcf Mon Sep 17 00:00:00 2001 From: Cai Bear Date: Sun, 10 Aug 2025 17:44:24 -0700 Subject: [PATCH 1/6] Add Image::fetch_with_level. --- crates/spirv-std/src/image.rs | 29 +++++++++++++++++++ .../compiletests/ui/image/fetch_with_level.rs | 13 +++++++++ 2 files changed, 42 insertions(+) create mode 100644 tests/compiletests/ui/image/fetch_with_level.rs diff --git a/crates/spirv-std/src/image.rs b/crates/spirv-std/src/image.rs index 361cd1cf29..f110a1dfba 100644 --- a/crates/spirv-std/src/image.rs +++ b/crates/spirv-std/src/image.rs @@ -162,6 +162,35 @@ impl< } result.truncate_into() } + + /// Fetch a single texel at a mipmap `level` with a sampler set at compile time + #[crate::macros::gpu_only] + #[doc(alias = "OpImageFetch")] + pub fn fetch_with_level( + &self, + coordinate: impl ImageCoordinate, + level: u32, + ) -> SampledType::SampleResult + where + I: Integer, + { + let mut result = SampledType::Vec4::default(); + unsafe { + asm! { + "OpDecorate %image NonUniform", + "OpDecorate %result NonUniform", + "%image = OpLoad _ {this}", + "%coordinate = OpLoad _ {coordinate}", + "%result = OpImageFetch typeof*{result} %image %coordinate Lod {level}", + "OpStore {result} %result", + result = in(reg) &mut result, + this = in(reg) self, + coordinate = in(reg) &coordinate, + level = in(reg) level, + } + } + result.truncate_into() + } } impl< diff --git a/tests/compiletests/ui/image/fetch_with_level.rs b/tests/compiletests/ui/image/fetch_with_level.rs new file mode 100644 index 0000000000..34ddb41ace --- /dev/null +++ b/tests/compiletests/ui/image/fetch_with_level.rs @@ -0,0 +1,13 @@ +// build-pass + +use spirv_std::spirv; +use spirv_std::{Image, arch}; + +#[spirv(fragment)] +pub fn main( + #[spirv(descriptor_set = 0, binding = 0)] image: &Image!(2D, type=f32, sampled), + output: &mut glam::Vec4, +) { + let texel = image.fetch_with_level(glam::IVec2::new(0, 1), 0); + *output = texel; +} From ba4bfe7a6250ff81a94a68710cec7377fedee360 Mon Sep 17 00:00:00 2001 From: Cai Bear Date: Mon, 11 Aug 2025 16:41:59 -0700 Subject: [PATCH 2/6] Rename level to lod to match spirv and glsl naming convention. --- crates/spirv-std/src/image.rs | 10 +++++----- .../image/{fetch_with_level.rs => fetch_with_lod.rs} | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) rename tests/compiletests/ui/image/{fetch_with_level.rs => fetch_with_lod.rs} (78%) diff --git a/crates/spirv-std/src/image.rs b/crates/spirv-std/src/image.rs index f110a1dfba..f3414084d1 100644 --- a/crates/spirv-std/src/image.rs +++ b/crates/spirv-std/src/image.rs @@ -163,13 +163,13 @@ impl< result.truncate_into() } - /// Fetch a single texel at a mipmap `level` with a sampler set at compile time + /// Fetch a single texel at a mipmap `lod` with a sampler set at compile time #[crate::macros::gpu_only] #[doc(alias = "OpImageFetch")] - pub fn fetch_with_level( + pub fn fetch_with_lod( &self, coordinate: impl ImageCoordinate, - level: u32, + lod: u32, ) -> SampledType::SampleResult where I: Integer, @@ -181,12 +181,12 @@ impl< "OpDecorate %result NonUniform", "%image = OpLoad _ {this}", "%coordinate = OpLoad _ {coordinate}", - "%result = OpImageFetch typeof*{result} %image %coordinate Lod {level}", + "%result = OpImageFetch typeof*{result} %image %coordinate Lod {lod}", "OpStore {result} %result", result = in(reg) &mut result, this = in(reg) self, coordinate = in(reg) &coordinate, - level = in(reg) level, + lod = in(reg) lod, } } result.truncate_into() diff --git a/tests/compiletests/ui/image/fetch_with_level.rs b/tests/compiletests/ui/image/fetch_with_lod.rs similarity index 78% rename from tests/compiletests/ui/image/fetch_with_level.rs rename to tests/compiletests/ui/image/fetch_with_lod.rs index 34ddb41ace..1b2662de46 100644 --- a/tests/compiletests/ui/image/fetch_with_level.rs +++ b/tests/compiletests/ui/image/fetch_with_lod.rs @@ -8,6 +8,6 @@ pub fn main( #[spirv(descriptor_set = 0, binding = 0)] image: &Image!(2D, type=f32, sampled), output: &mut glam::Vec4, ) { - let texel = image.fetch_with_level(glam::IVec2::new(0, 1), 0); + let texel = image.fetch_with_lod(glam::IVec2::new(0, 1), 0); *output = texel; } From 3389d2be56d56108920e0d5de6ab8f72f3f9ba51 Mon Sep 17 00:00:00 2001 From: Cai Bear Date: Tue, 12 Aug 2025 14:16:02 -0700 Subject: [PATCH 3/6] Use fetch_with to simplify implementation. --- crates/spirv-std/src/image.rs | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/crates/spirv-std/src/image.rs b/crates/spirv-std/src/image.rs index f3414084d1..26dd7e3e37 100644 --- a/crates/spirv-std/src/image.rs +++ b/crates/spirv-std/src/image.rs @@ -174,22 +174,7 @@ impl< where I: Integer, { - let mut result = SampledType::Vec4::default(); - unsafe { - asm! { - "OpDecorate %image NonUniform", - "OpDecorate %result NonUniform", - "%image = OpLoad _ {this}", - "%coordinate = OpLoad _ {coordinate}", - "%result = OpImageFetch typeof*{result} %image %coordinate Lod {lod}", - "OpStore {result} %result", - result = in(reg) &mut result, - this = in(reg) self, - coordinate = in(reg) &coordinate, - lod = in(reg) lod, - } - } - result.truncate_into() + self.fetch_with(coordinate, sample_with::lod(lod)) } } From e8d31df4a39c6444f4f7f2dbaf7aadee8d06b13e Mon Sep 17 00:00:00 2001 From: Cai Bear Date: Tue, 12 Aug 2025 14:31:11 -0700 Subject: [PATCH 4/6] Add comment that mentions level. --- crates/spirv-std/src/image.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/spirv-std/src/image.rs b/crates/spirv-std/src/image.rs index 26dd7e3e37..d07710cef0 100644 --- a/crates/spirv-std/src/image.rs +++ b/crates/spirv-std/src/image.rs @@ -164,6 +164,8 @@ impl< } /// Fetch a single texel at a mipmap `lod` with a sampler set at compile time + /// + /// `lod` is also known as `level` in WGSL's `textureLoad` #[crate::macros::gpu_only] #[doc(alias = "OpImageFetch")] pub fn fetch_with_lod( From b9730b78af359afce88964cb59bf942d2f6ad824 Mon Sep 17 00:00:00 2001 From: Cai Bear Date: Fri, 15 Aug 2025 22:47:29 -0700 Subject: [PATCH 5/6] Fix failing compiletests. --- tests/compiletests/ui/image/gather_err.stderr | 12 ++++++------ .../ui/image/query/query_levels_err.stderr | 8 ++++---- .../compiletests/ui/image/query/query_lod_err.stderr | 6 +++--- .../ui/image/query/query_size_err.stderr | 8 ++++---- .../ui/image/query/query_size_lod_err.stderr | 6 +++--- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/compiletests/ui/image/gather_err.stderr b/tests/compiletests/ui/image/gather_err.stderr index 550fdfd018..a2d0519500 100644 --- a/tests/compiletests/ui/image/gather_err.stderr +++ b/tests/compiletests/ui/image/gather_err.stderr @@ -9,12 +9,12 @@ error[E0277]: the trait bound `Image: HasGather` is no Image Image note: required by a bound in `Image::::gather` - --> $SPIRV_STD_SRC/image.rs:199:15 + --> $SPIRV_STD_SRC/image.rs:215:15 | -192 | pub fn gather( +208 | pub fn gather( | ------ required by a bound in this associated function ... -199 | Self: HasGather, +215 | Self: HasGather, | ^^^^^^^^^ required by this bound in `Image::::gather` error[E0277]: the trait bound `Image: HasGather` is not satisfied @@ -28,12 +28,12 @@ error[E0277]: the trait bound `Image: HasGather` is no Image Image note: required by a bound in `Image::::gather` - --> $SPIRV_STD_SRC/image.rs:199:15 + --> $SPIRV_STD_SRC/image.rs:215:15 | -192 | pub fn gather( +208 | pub fn gather( | ------ required by a bound in this associated function ... -199 | Self: HasGather, +215 | Self: HasGather, | ^^^^^^^^^ required by this bound in `Image::::gather` error: aborting due to 2 previous errors diff --git a/tests/compiletests/ui/image/query/query_levels_err.stderr b/tests/compiletests/ui/image/query/query_levels_err.stderr index c49926bd05..dd3220d9f3 100644 --- a/tests/compiletests/ui/image/query/query_levels_err.stderr +++ b/tests/compiletests/ui/image/query/query_levels_err.stderr @@ -10,12 +10,12 @@ error[E0277]: the trait bound `Image: HasQueryLevels` Image Image note: required by a bound in `Image::::query_levels` - --> $SPIRV_STD_SRC/image.rs:951:15 + --> $SPIRV_STD_SRC/image.rs:967:15 | -949 | pub fn query_levels(&self) -> u32 +965 | pub fn query_levels(&self) -> u32 | ------------ required by a bound in this associated function -950 | where -951 | Self: HasQueryLevels, +966 | where +967 | Self: HasQueryLevels, | ^^^^^^^^^^^^^^ required by this bound in `Image::::query_levels` error: aborting due to 1 previous error diff --git a/tests/compiletests/ui/image/query/query_lod_err.stderr b/tests/compiletests/ui/image/query/query_lod_err.stderr index e985e690b5..868bab22da 100644 --- a/tests/compiletests/ui/image/query/query_lod_err.stderr +++ b/tests/compiletests/ui/image/query/query_lod_err.stderr @@ -10,12 +10,12 @@ error[E0277]: the trait bound `Image: HasQueryLevels` Image Image note: required by a bound in `Image::::query_lod` - --> $SPIRV_STD_SRC/image.rs:980:15 + --> $SPIRV_STD_SRC/image.rs:996:15 | -974 | pub fn query_lod( +990 | pub fn query_lod( | --------- required by a bound in this associated function ... -980 | Self: HasQueryLevels, +996 | Self: HasQueryLevels, | ^^^^^^^^^^^^^^ required by this bound in `Image::::query_lod` error: aborting due to 1 previous error diff --git a/tests/compiletests/ui/image/query/query_size_err.stderr b/tests/compiletests/ui/image/query/query_size_err.stderr index c94971162e..cdbd9245f5 100644 --- a/tests/compiletests/ui/image/query/query_size_err.stderr +++ b/tests/compiletests/ui/image/query/query_size_err.stderr @@ -15,12 +15,12 @@ error[E0277]: the trait bound `Image: HasQuerySize` is Image and 6 others note: required by a bound in `Image::::query_size` - --> $SPIRV_STD_SRC/image.rs:1015:15 + --> $SPIRV_STD_SRC/image.rs:1031:15 | -1013 | pub fn query_size + Default>(&self) -> Size +1029 | pub fn query_size + Default>(&self) -> Size | ---------- required by a bound in this associated function -1014 | where -1015 | Self: HasQuerySize, +1030 | where +1031 | Self: HasQuerySize, | ^^^^^^^^^^^^ required by this bound in `Image::::query_size` error: aborting due to 1 previous error diff --git a/tests/compiletests/ui/image/query/query_size_lod_err.stderr b/tests/compiletests/ui/image/query/query_size_lod_err.stderr index bbad070b0a..69662c8e79 100644 --- a/tests/compiletests/ui/image/query/query_size_lod_err.stderr +++ b/tests/compiletests/ui/image/query/query_size_lod_err.stderr @@ -10,12 +10,12 @@ error[E0277]: the trait bound `Image: HasQuerySizeLod` Image Image note: required by a bound in `Image::::query_size_lod` - --> $SPIRV_STD_SRC/image.rs:1061:15 + --> $SPIRV_STD_SRC/image.rs:1077:15 | -1056 | pub fn query_size_lod + Default>( +1072 | pub fn query_size_lod + Default>( | -------------- required by a bound in this associated function ... -1061 | Self: HasQuerySizeLod, +1077 | Self: HasQuerySizeLod, | ^^^^^^^^^^^^^^^ required by this bound in `Image::::query_size_lod` error: aborting due to 1 previous error From 6772641fb977510905b6f0f18627583cadd442d6 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Sat, 16 Aug 2025 20:42:22 -0700 Subject: [PATCH 6/6] Fix compiletests on macos --- .../query/sampled_image_rect_query_size_lod_err.stderr | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr b/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr index 32c369a9bd..0b3bcea2ab 100644 --- a/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr +++ b/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr @@ -10,12 +10,12 @@ error[E0277]: the trait bound `Image: HasQuerySizeLod` Image Image note: required by a bound in `SampledImage::>::query_size_lod` - --> /image.rs:1226:12 + --> /image.rs:1242:12 | -1212 | pub fn query_size_lod + Default>( +1228 | pub fn query_size_lod + Default>( | -------------- required by a bound in this associated function ... -1226 | >: HasQuerySizeLod, +1242 | >: HasQuerySizeLod, | ^^^^^^^^^^^^^^^ required by this bound in `SampledImage::>::query_size_lod` error: aborting due to 1 previous error