Skip to content

Commit 9fb930b

Browse files
authored
feat: add OpImageSampleExplicitLod to spirv-std (#498)
1 parent 27eb1d1 commit 9fb930b

File tree

3 files changed

+154
-0
lines changed

3 files changed

+154
-0
lines changed

crates/spirv-std/src/textures.rs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,65 @@ impl Image2d {
4646
result
4747
}
4848
}
49+
#[spirv_std_macros::gpu_only]
50+
#[cfg(feature = "const-generics")]
51+
/// Sample the image at a coordinate by a lod
52+
pub fn sample_by_lod<V: Vector<f32, 4>>(
53+
&self,
54+
sampler: Sampler,
55+
coordinate: impl Vector<f32, 2>,
56+
lod: f32,
57+
) -> V {
58+
let mut result = Default::default();
59+
unsafe {
60+
asm!(
61+
"%image = OpLoad _ {this}",
62+
"%sampler = OpLoad _ {sampler}",
63+
"%coordinate = OpLoad _ {coordinate}",
64+
"%lod = OpLoad _ {lod}",
65+
"%sampledImage = OpSampledImage _ %image %sampler",
66+
"%result = OpImageSampleExplicitLod _ %sampledImage %coordinate Lod %lod",
67+
"OpStore {result} %result",
68+
result = in(reg) &mut result,
69+
this = in(reg) self,
70+
sampler = in(reg) &sampler,
71+
coordinate = in(reg) &coordinate,
72+
lod = in(reg) &lod
73+
);
74+
}
75+
result
76+
}
77+
#[spirv_std_macros::gpu_only]
78+
#[cfg(feature = "const-generics")]
79+
/// Sample the image based on a gradient formed by (dx, dy). Specifically, ([du/dx, dv/dx], [du/dy, dv/dy])
80+
pub fn sample_by_gradient<V: Vector<f32, 4>>(
81+
&self,
82+
sampler: Sampler,
83+
coordinate: impl Vector<f32, 2>,
84+
gradient_dx: impl Vector<f32, 2>,
85+
gradient_dy: impl Vector<f32, 2>,
86+
) -> V {
87+
let mut result = Default::default();
88+
unsafe {
89+
asm!(
90+
"%image = OpLoad _ {this}",
91+
"%sampler = OpLoad _ {sampler}",
92+
"%coordinate = OpLoad _ {coordinate}",
93+
"%gradient_dx = OpLoad _ {gradient_dx}",
94+
"%gradient_dy = OpLoad _ {gradient_dy}",
95+
"%sampledImage = OpSampledImage _ %image %sampler",
96+
"%result = OpImageSampleExplicitLod _ %sampledImage %coordinate Grad %gradient_dx %gradient_dy",
97+
"OpStore {result} %result",
98+
result = in(reg) &mut result,
99+
this = in(reg) self,
100+
sampler = in(reg) &sampler,
101+
coordinate = in(reg) &coordinate,
102+
gradient_dx = in(reg) &gradient_dx,
103+
gradient_dy = in(reg) &gradient_dy,
104+
);
105+
}
106+
result
107+
}
49108
/// Fetch a single texel with a sampler set at compile time
50109
#[spirv_std_macros::gpu_only]
51110
#[cfg(feature = "const-generics")]
@@ -172,6 +231,65 @@ impl Image2dArray {
172231
result
173232
}
174233
}
234+
#[spirv_std_macros::gpu_only]
235+
#[cfg(feature = "const-generics")]
236+
/// Sample the image at a coordinate by a lod
237+
pub fn sample_by_lod<V: Vector<f32, 4>>(
238+
&self,
239+
sampler: Sampler,
240+
coordinate: impl Vector<f32, 3>,
241+
lod: f32,
242+
) -> V {
243+
let mut result = Default::default();
244+
unsafe {
245+
asm!(
246+
"%image = OpLoad _ {this}",
247+
"%sampler = OpLoad _ {sampler}",
248+
"%coordinate = OpLoad _ {coordinate}",
249+
"%lod = OpLoad _ {lod}",
250+
"%sampledImage = OpSampledImage _ %image %sampler",
251+
"%result = OpImageSampleExplicitLod _ %sampledImage %coordinate Lod %lod",
252+
"OpStore {result} %result",
253+
result = in(reg) &mut result,
254+
this = in(reg) self,
255+
sampler = in(reg) &sampler,
256+
coordinate = in(reg) &coordinate,
257+
lod = in(reg) &lod
258+
);
259+
}
260+
result
261+
}
262+
#[spirv_std_macros::gpu_only]
263+
#[cfg(feature = "const-generics")]
264+
/// Sample the image based on a gradient formed by (dx, dy). Specifically, ([du/dx, dv/dx], [du/dy, dv/dy])
265+
pub fn sample_by_gradient<V: Vector<f32, 4>>(
266+
&self,
267+
sampler: Sampler,
268+
coordinate: impl Vector<f32, 3>,
269+
gradient_dx: impl Vector<f32, 2>,
270+
gradient_dy: impl Vector<f32, 2>,
271+
) -> V {
272+
let mut result = Default::default();
273+
unsafe {
274+
asm!(
275+
"%image = OpLoad _ {this}",
276+
"%sampler = OpLoad _ {sampler}",
277+
"%coordinate = OpLoad _ {coordinate}",
278+
"%gradient_dx = OpLoad _ {gradient_dx}",
279+
"%gradient_dy = OpLoad _ {gradient_dy}",
280+
"%sampledImage = OpSampledImage _ %image %sampler",
281+
"%result = OpImageSampleExplicitLod _ %sampledImage %coordinate Grad %gradient_dx %gradient_dy",
282+
"OpStore {result} %result",
283+
result = in(reg) &mut result,
284+
this = in(reg) self,
285+
sampler = in(reg) &sampler,
286+
coordinate = in(reg) &coordinate,
287+
gradient_dx = in(reg) &gradient_dx,
288+
gradient_dy = in(reg) &gradient_dy,
289+
);
290+
}
291+
result
292+
}
175293
}
176294

177295
#[spirv(sampled_image)]

tests/ui/image/sample_gradient.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Test `OpImageSampleExplicitLod`
2+
// build-pass
3+
4+
use spirv_std::{arch, storage_class::{Output, UniformConstant}, Image2d, Image2dArray, Sampler};
5+
6+
#[spirv(fragment)]
7+
pub fn main(
8+
image: UniformConstant<Image2d>,
9+
image_array: UniformConstant<Image2dArray>,
10+
sampler: UniformConstant<Sampler>,
11+
mut image_output: Output<glam::Vec4>,
12+
mut image_array_output: Output<glam::Vec4>,
13+
) {
14+
let image_result = image.sample_by_gradient(*sampler, glam::Vec2::new(0.0, 1.0), glam::Vec2::new(0.0, 1.0), glam::Vec2::new(0.0, 1.0));
15+
*image_output = image_result;
16+
let image_array_result = image_array.sample_by_gradient(*sampler, glam::Vec3A::new(0.0, 0.0, 1.0), glam::Vec2::new(0.0, 1.0), glam::Vec2::new(0.0, 1.0));
17+
*image_array_output = image_array_result;
18+
}

tests/ui/image/sample_lod.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Test `OpImageSampleExplicitLod`
2+
// build-pass
3+
4+
use spirv_std::{arch, storage_class::{Output, UniformConstant}, Image2d, Image2dArray, Sampler};
5+
6+
#[spirv(fragment)]
7+
pub fn main(
8+
image: UniformConstant<Image2d>,
9+
image_array: UniformConstant<Image2dArray>,
10+
sampler: UniformConstant<Sampler>,
11+
mut image_output: Output<glam::Vec4>,
12+
mut image_array_output: Output<glam::Vec4>,
13+
) {
14+
let image_result = image.sample_by_lod(*sampler, glam::Vec2::new(0.0, 1.0), 0.0);
15+
*image_output = image_result;
16+
let image_array_result = image_array.sample_by_lod(*sampler, glam::Vec3A::new(0.0, 0.0, 1.0), 0.0);
17+
*image_array_output = image_array_result;
18+
}

0 commit comments

Comments
 (0)