Skip to content

Commit 5304c3c

Browse files
committed
[naga wgsl-in] Apply automatic conversions to sampling arguments.
Properly apply WGSL's automatic conversions to the arguments to texture sampling functions. Introduce helper function `Lowerer::expression_with_leaf_scalar`. Although this can't affect behavior, use `Lowerer::expression_for_abstract` for the `image` and `sampler` arguments, simply because we want to move away from `Lower::expression`'s automatic concretization, and move towards having callers say explicitly what sort of conversions they need. Although this can't affect behavior, use `Lowerer::expression_with_leaf_scalar` for the `offset` argument, so that the code spells out that this requires an `i32` value, rather than depending on blind concretization giving it that. Continue to use `Lowerer::expression` for `gather` and `array_index`, since those happen to behave correctly with blind concretization, and can be cleaned up later. Fixes gfx-rs#7427.
1 parent 6cd6561 commit 5304c3c

4 files changed

Lines changed: 90 additions & 12 deletions

File tree

naga/src/front/wgsl/lower/mod.rs

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2025,6 +2025,16 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
20252025
ctx.apply_load_rule(expr)
20262026
}
20272027

2028+
fn expression_with_leaf_scalar(
2029+
&mut self,
2030+
expr: Handle<ast::Expression<'source>>,
2031+
scalar: ir::Scalar,
2032+
ctx: &mut ExpressionContext<'source, '_, '_>,
2033+
) -> Result<'source, Handle<ir::Expression>> {
2034+
let unconverted = self.expression_for_abstract(expr, ctx)?;
2035+
ctx.try_automatic_conversion_for_leaf_scalar(unconverted, scalar, Span::default())
2036+
}
2037+
20282038
fn expression_for_reference(
20292039
&mut self,
20302040
expr: Handle<ast::Expression<'source>>,
@@ -3272,7 +3282,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
32723282
) -> Result<'source, (Handle<ir::Expression>, Span)> {
32733283
let image = args.next()?;
32743284
let image_span = ctx.ast_expressions.get_span(image);
3275-
let image = lowerer.expression(image, ctx)?;
3285+
let image = lowerer.expression_for_abstract(image, ctx)?;
32763286
Ok((image, image_span))
32773287
}
32783288

@@ -3316,11 +3326,11 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
33163326
}
33173327
};
33183328

3319-
let sampler = self.expression(args.next()?, ctx)?;
3329+
let sampler = self.expression_for_abstract(args.next()?, ctx)?;
33203330

3321-
let coordinate = self.expression(args.next()?, ctx)?;
3331+
let coordinate = self.expression_with_leaf_scalar(args.next()?, ir::Scalar::F32, ctx)?;
33223332

3323-
let (_, arrayed) = ctx.image_data(image, image_span)?;
3333+
let (class, arrayed) = ctx.image_data(image, image_span)?;
33243334
let array_index = arrayed
33253335
.then(|| self.expression(args.next()?, ctx))
33263336
.transpose()?;
@@ -3333,7 +3343,8 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
33333343
depth_ref = None;
33343344
}
33353345
Texture::GatherCompare => {
3336-
let reference = self.expression(args.next()?, ctx)?;
3346+
let reference =
3347+
self.expression_with_leaf_scalar(args.next()?, ir::Scalar::F32, ctx)?;
33373348
level = ir::SampleLevel::Zero;
33383349
depth_ref = Some(reference);
33393350
}
@@ -3343,36 +3354,52 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
33433354
depth_ref = None;
33443355
}
33453356
Texture::SampleBias => {
3346-
let bias = self.expression(args.next()?, ctx)?;
3357+
let bias = self.expression_with_leaf_scalar(args.next()?, ir::Scalar::F32, ctx)?;
33473358
level = ir::SampleLevel::Bias(bias);
33483359
depth_ref = None;
33493360
}
33503361
Texture::SampleCompare => {
3351-
let reference = self.expression(args.next()?, ctx)?;
3362+
let reference =
3363+
self.expression_with_leaf_scalar(args.next()?, ir::Scalar::F32, ctx)?;
33523364
level = ir::SampleLevel::Auto;
33533365
depth_ref = Some(reference);
33543366
}
33553367
Texture::SampleCompareLevel => {
3356-
let reference = self.expression(args.next()?, ctx)?;
3368+
let reference =
3369+
self.expression_with_leaf_scalar(args.next()?, ir::Scalar::F32, ctx)?;
33573370
level = ir::SampleLevel::Zero;
33583371
depth_ref = Some(reference);
33593372
}
33603373
Texture::SampleGrad => {
3361-
let x = self.expression(args.next()?, ctx)?;
3362-
let y = self.expression(args.next()?, ctx)?;
3374+
let x = self.expression_with_leaf_scalar(args.next()?, ir::Scalar::F32, ctx)?;
3375+
let y = self.expression_with_leaf_scalar(args.next()?, ir::Scalar::F32, ctx)?;
33633376
level = ir::SampleLevel::Gradient { x, y };
33643377
depth_ref = None;
33653378
}
33663379
Texture::SampleLevel => {
3367-
let exact = self.expression(args.next()?, ctx)?;
3380+
let exact = match class {
3381+
// When applied to depth textures, `textureSampleLevel`'s
3382+
// `level` argument is an `i32` or `u32`.
3383+
ir::ImageClass::Depth { .. } => self.expression(args.next()?, ctx)?,
3384+
3385+
// When applied to other sampled types, its `level` argument
3386+
// is an `f32`.
3387+
ir::ImageClass::Sampled { .. } => {
3388+
self.expression_with_leaf_scalar(args.next()?, ir::Scalar::F32, ctx)?
3389+
}
3390+
3391+
// Sampling `Storage` textures isn't allowed at all. Let the
3392+
// validator report the error.
3393+
ir::ImageClass::Storage { .. } => self.expression(args.next()?, ctx)?,
3394+
};
33683395
level = ir::SampleLevel::Exact(exact);
33693396
depth_ref = None;
33703397
}
33713398
};
33723399

33733400
let offset = args
33743401
.next()
3375-
.map(|arg| self.expression(arg, &mut ctx.as_const()))
3402+
.map(|arg| self.expression_with_leaf_scalar(arg, ir::Scalar::I32, &mut ctx.as_const()))
33763403
.ok()
33773404
.transpose()?;
33783405

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
targets = "METAL"
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
@group(0) @binding(0) var t: texture_2d<f32>;
2+
@group(0) @binding(1) var s: sampler;
3+
4+
fn color() {
5+
_ = textureSample(t, s, vec2(1,2));
6+
_ = textureSample(t, s, vec2(1,2), vec2(3,4));
7+
_ = textureSampleLevel(t, s, vec2(1,2), 0);
8+
_ = textureSampleLevel(t, s, vec2(1,2), 0.0);
9+
_ = textureSampleGrad(t, s, vec2(1,2), vec2(3,4), vec2(5,6));
10+
_ = textureSampleBias(t, s, vec2(1,2), 1);
11+
}
12+
13+
@group(0) @binding(2) var d: texture_depth_2d;
14+
@group(0) @binding(3) var c: sampler_comparison;
15+
16+
fn depth() {
17+
_ = textureSampleLevel(d, s, vec2(1,2), 1i);
18+
_ = textureSampleCompare(d, c, vec2(1,2), 0);
19+
_ = textureGatherCompare(d, c, vec2(1,2), 0);
20+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// language: metal1.0
2+
#include <metal_stdlib>
3+
#include <simd/simd.h>
4+
5+
using metal::uint;
6+
7+
8+
void color(
9+
metal::texture2d<float, metal::access::sample> t,
10+
metal::sampler s
11+
) {
12+
metal::float4 phony = t.sample(s, metal::float2(1.0, 2.0));
13+
metal::float4 phony_1 = t.sample(s, metal::float2(1.0, 2.0), metal::int2(3, 4));
14+
metal::float4 phony_2 = t.sample(s, metal::float2(1.0, 2.0), metal::level(0.0));
15+
metal::float4 phony_3 = t.sample(s, metal::float2(1.0, 2.0), metal::level(0.0));
16+
metal::float4 phony_4 = t.sample(s, metal::float2(1.0, 2.0), metal::gradient2d(metal::float2(3.0, 4.0), metal::float2(5.0, 6.0)));
17+
metal::float4 phony_5 = t.sample(s, metal::float2(1.0, 2.0), metal::bias(1.0));
18+
return;
19+
}
20+
21+
void depth(
22+
metal::sampler s,
23+
metal::depth2d<float, metal::access::sample> d,
24+
metal::sampler c
25+
) {
26+
float phony_6 = d.sample(s, metal::float2(1.0, 2.0), metal::level(1));
27+
float phony_7 = d.sample_compare(c, metal::float2(1.0, 2.0), 0.0);
28+
metal::float4 phony_8 = d.gather_compare(c, metal::float2(1.0, 2.0), 0.0);
29+
return;
30+
}

0 commit comments

Comments
 (0)