Skip to content

Commit 92a1702

Browse files
authored
[naga wgsl-in] Add support for unsigned types when calling textureLoad with the level parameter. (#7058)
1 parent 031ed26 commit 92a1702

File tree

11 files changed

+685
-617
lines changed

11 files changed

+685
-617
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ By @cwfitzgerald in [#7030](https://github.com/gfx-rs/wgpu/pull/7030).
136136
137137
#### Naga
138138
139+
- Add support for unsigned types when calling textureLoad with the level parameter. By @ygdrasil-io in [#7058](https://github.com/gfx-rs/wgpu/pull/7058).
139140
- Support @must_use attribute on function declarations. By @turbocrime in [#6801](https://github.com/gfx-rs/wgpu/pull/6801).
140141
- Support for generating the candidate intersections from AABB geometry, and confirming the hits. By @kvark in [#7047](https://github.com/gfx-rs/wgpu/pull/7047).
141142
- Make naga::back::spv::Function::to_words write the OpFunctionEnd instruction in itself, instead of making another call after it. By @junjunjd in [#7156](https://github.com/gfx-rs/wgpu/pull/7156).

naga/src/back/glsl/mod.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4449,10 +4449,28 @@ impl<'a, W: Write> Writer<'a, W> {
44494449
writeln!(self.out, ") - 1)")?;
44504450
}
44514451
} else if let Some(sample_or_level) = sample.or(level) {
4452+
// GLSL only support SInt on this field while WGSL support also UInt
4453+
let cast_to_int = matches!(
4454+
*ctx.resolve_type(sample_or_level, &self.module.types),
4455+
TypeInner::Scalar(crate::Scalar {
4456+
kind: crate::ScalarKind::Uint,
4457+
..
4458+
})
4459+
);
4460+
44524461
// If no bounds checking is need just add the sample or level argument
44534462
// after the coordinates
44544463
write!(self.out, ", ")?;
4464+
4465+
if cast_to_int {
4466+
write!(self.out, "int(")?;
4467+
}
4468+
44554469
self.write_expr(sample_or_level, ctx)?;
4470+
4471+
if cast_to_int {
4472+
write!(self.out, ")")?;
4473+
}
44564474
}
44574475

44584476
// Close the image load function.

naga/src/back/hlsl/help.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,8 +1611,26 @@ impl<W: Write> super::Writer<'_, W> {
16111611
self.write_expr(module, expr, func_ctx)?;
16121612
}
16131613
if let Some(expr) = mip_level {
1614+
// Explicit cast if needed
1615+
let cast_to_int = matches!(
1616+
*func_ctx.resolve_type(expr, &module.types),
1617+
crate::TypeInner::Scalar(crate::Scalar {
1618+
kind: ScalarKind::Uint,
1619+
..
1620+
})
1621+
);
1622+
16141623
write!(self.out, ", ")?;
1624+
1625+
if cast_to_int {
1626+
write!(self.out, "int(")?;
1627+
}
1628+
16151629
self.write_expr(module, expr, func_ctx)?;
1630+
1631+
if cast_to_int {
1632+
write!(self.out, ")")?;
1633+
}
16161634
}
16171635
write!(self.out, ")")?;
16181636
}

naga/src/back/hlsl/writer.rs

Lines changed: 67 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3213,57 +3213,16 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
32133213
array_index,
32143214
sample,
32153215
level,
3216-
} => {
3217-
let mut wrapping_type = None;
3218-
match *func_ctx.resolve_type(image, &module.types) {
3219-
TypeInner::Image {
3220-
class: crate::ImageClass::Storage { format, .. },
3221-
..
3222-
} => {
3223-
if format.single_component() {
3224-
wrapping_type = Some(Scalar::from(format));
3225-
}
3226-
}
3227-
_ => {}
3228-
}
3229-
if let Some(scalar) = wrapping_type {
3230-
write!(
3231-
self.out,
3232-
"{}{}(",
3233-
help::IMAGE_STORAGE_LOAD_SCALAR_WRAPPER,
3234-
scalar.to_hlsl_str()?
3235-
)?;
3236-
}
3237-
// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-to-load
3238-
self.write_expr(module, image, func_ctx)?;
3239-
write!(self.out, ".Load(")?;
3240-
3241-
self.write_texture_coordinates(
3242-
"int",
3243-
coordinate,
3244-
array_index,
3245-
level,
3246-
module,
3247-
func_ctx,
3248-
)?;
3249-
3250-
if let Some(sample) = sample {
3251-
write!(self.out, ", ")?;
3252-
self.write_expr(module, sample, func_ctx)?;
3253-
}
3254-
3255-
// close bracket for Load function
3256-
write!(self.out, ")")?;
3257-
3258-
if wrapping_type.is_some() {
3259-
write!(self.out, ")")?;
3260-
}
3261-
3262-
// return x component if return type is scalar
3263-
if let TypeInner::Scalar(_) = *func_ctx.resolve_type(expr, &module.types) {
3264-
write!(self.out, ".x")?;
3265-
}
3266-
}
3216+
} => self.write_image_load(
3217+
&module,
3218+
expr,
3219+
func_ctx,
3220+
image,
3221+
coordinate,
3222+
array_index,
3223+
sample,
3224+
level,
3225+
)?,
32673226
Expression::GlobalVariable(handle) => {
32683227
let global_variable = &module.global_variables[handle];
32693228
let ty = &module.types[global_variable.ty].inner;
@@ -4003,6 +3962,63 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
40033962
Ok(())
40043963
}
40053964

3965+
#[allow(clippy::too_many_arguments)]
3966+
fn write_image_load(
3967+
&mut self,
3968+
module: &&Module,
3969+
expr: Handle<crate::Expression>,
3970+
func_ctx: &back::FunctionCtx,
3971+
image: Handle<crate::Expression>,
3972+
coordinate: Handle<crate::Expression>,
3973+
array_index: Option<Handle<crate::Expression>>,
3974+
sample: Option<Handle<crate::Expression>>,
3975+
level: Option<Handle<crate::Expression>>,
3976+
) -> Result<(), Error> {
3977+
let mut wrapping_type = None;
3978+
match *func_ctx.resolve_type(image, &module.types) {
3979+
TypeInner::Image {
3980+
class: crate::ImageClass::Storage { format, .. },
3981+
..
3982+
} => {
3983+
if format.single_component() {
3984+
wrapping_type = Some(Scalar::from(format));
3985+
}
3986+
}
3987+
_ => {}
3988+
}
3989+
if let Some(scalar) = wrapping_type {
3990+
write!(
3991+
self.out,
3992+
"{}{}(",
3993+
help::IMAGE_STORAGE_LOAD_SCALAR_WRAPPER,
3994+
scalar.to_hlsl_str()?
3995+
)?;
3996+
}
3997+
// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-to-load
3998+
self.write_expr(module, image, func_ctx)?;
3999+
write!(self.out, ".Load(")?;
4000+
4001+
self.write_texture_coordinates("int", coordinate, array_index, level, module, func_ctx)?;
4002+
4003+
if let Some(sample) = sample {
4004+
write!(self.out, ", ")?;
4005+
self.write_expr(module, sample, func_ctx)?;
4006+
}
4007+
4008+
// close bracket for Load function
4009+
write!(self.out, ")")?;
4010+
4011+
if wrapping_type.is_some() {
4012+
write!(self.out, ")")?;
4013+
}
4014+
4015+
// return x component if return type is scalar
4016+
if let TypeInner::Scalar(_) = *func_ctx.resolve_type(expr, &module.types) {
4017+
write!(self.out, ".x")?;
4018+
}
4019+
Ok(())
4020+
}
4021+
40064022
/// Find the [`BindingArraySamplerInfo`] from an expression so that such an access
40074023
/// can be generated later.
40084024
fn sampler_binding_array_info_from_expression(

naga/src/valid/expression.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -671,11 +671,15 @@ impl super::Validator {
671671

672672
match (level, class.is_mipmapped()) {
673673
(None, false) => {}
674-
(Some(level), true) => {
675-
if resolver[level].scalar_kind() != Some(Sk::Sint) {
676-
return Err(ExpressionError::InvalidImageOtherIndexType(level));
674+
(Some(level), true) => match resolver[level] {
675+
Ti::Scalar(Sc {
676+
kind: Sk::Sint | Sk::Uint,
677+
width: _,
678+
}) => {}
679+
_ => {
680+
return Err(ExpressionError::InvalidImageArrayIndexType(level))
677681
}
678-
}
682+
},
679683
_ => {
680684
return Err(ExpressionError::InvalidImageOtherIndex);
681685
}

naga/tests/in/image.wgsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ fn main(@builtin(local_invocation_id) local_id: vec3<u32>) {
2121
let itc = vec2<i32>(dim * local_id.xy) % vec2<i32>(10, 20);
2222
// loads with ivec2 coords.
2323
let value1 = textureLoad(image_mipmapped_src, itc, i32(local_id.z));
24+
// doing the same thing as the line above, but with u32, as textureLoad must also support unsigned integers.
25+
let value1_2 = textureLoad(image_mipmapped_src, itc, u32(local_id.z));
2426
let value2 = textureLoad(image_multisampled_src, itc, i32(local_id.z));
2527
let value4 = textureLoad(image_storage_src, itc);
2628
let value5 = textureLoad(image_array_src, itc, local_id.z, i32(local_id.z) + 1);

naga/tests/out/glsl/image.main.Compute.glsl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ void main() {
2020
uvec2 dim = uvec2(imageSize(_group_0_binding_1_cs).xy);
2121
ivec2 itc = (ivec2((dim * local_id.xy)) % ivec2(10, 20));
2222
uvec4 value1_ = texelFetch(_group_0_binding_0_cs, itc, int(local_id.z));
23+
uvec4 value1_2_ = texelFetch(_group_0_binding_0_cs, itc, int(uint(local_id.z)));
2324
uvec4 value2_ = texelFetch(_group_0_binding_3_cs, itc, int(local_id.z));
2425
uvec4 value4_ = imageLoad(_group_0_binding_1_cs, itc);
2526
uvec4 value5_ = texelFetch(_group_0_binding_5_cs, ivec3(itc, local_id.z), (int(local_id.z) + 1));

naga/tests/out/hlsl/image.hlsl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ void main(uint3 local_id : SV_GroupThreadID)
4242
uint2 dim = NagaRWDimensions2D(image_storage_src);
4343
int2 itc = naga_mod(int2((dim * local_id.xy)), int2(int(10), int(20)));
4444
uint4 value1_ = image_mipmapped_src.Load(int3(itc, int(local_id.z)));
45+
uint4 value1_2_ = image_mipmapped_src.Load(int3(itc, int(uint(local_id.z))));
4546
uint4 value2_ = image_multisampled_src.Load(itc, int(local_id.z));
4647
uint4 value4_ = image_storage_src.Load(itc);
4748
uint4 value5_ = image_array_src.Load(int4(itc, local_id.z, asint(asuint(int(local_id.z)) + asuint(int(1)))));

naga/tests/out/msl/image.msl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ kernel void main_(
2424
metal::uint2 dim = metal::uint2(image_storage_src.get_width(), image_storage_src.get_height());
2525
metal::int2 itc = naga_mod(static_cast<metal::int2>(dim * local_id.xy), metal::int2(10, 20));
2626
metal::uint4 value1_ = image_mipmapped_src.read(metal::uint2(itc), static_cast<int>(local_id.z));
27+
metal::uint4 value1_2_ = image_mipmapped_src.read(metal::uint2(itc), static_cast<uint>(local_id.z));
2728
metal::uint4 value2_ = image_multisampled_src.read(metal::uint2(itc), static_cast<int>(local_id.z));
2829
metal::uint4 value4_ = image_storage_src.read(metal::uint2(itc));
2930
metal::uint4 value5_ = image_array_src.read(metal::uint2(itc), local_id.z, as_type<int>(as_type<uint>(static_cast<int>(local_id.z)) + as_type<uint>(1)));

0 commit comments

Comments
 (0)