Skip to content

Commit

Permalink
Allow array_index to be unsigned (#2298)
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda authored Apr 7, 2023
1 parent 99a7773 commit f59668c
Show file tree
Hide file tree
Showing 20 changed files with 2,328 additions and 1,421 deletions.
52 changes: 29 additions & 23 deletions src/back/spv/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,41 +314,47 @@ impl<'w> BlockContext<'w> {
};

// Convert the index to the coordinate component type, if necessary.
let array_index_i32_id = self.cached[array_index];
let reconciled_array_index_id = if component_kind == crate::ScalarKind::Sint {
array_index_i32_id
} else if component_kind == crate::ScalarKind::Uint {
let u32_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: crate::ScalarKind::Uint,
width: 4,
pointer_space: None,
}));

let reconciled_id = self.gen_id();
block.body.push(Instruction::unary(
spirv::Op::Bitcast,
u32_id,
reconciled_id,
array_index_i32_id,
let array_index_id = self.cached[array_index];
let ty = &self.fun_info[array_index].ty;
let inner_ty = ty.inner_with(&self.ir_module.types);
let array_index_kind = if let Ti::Scalar { kind, width: 4 } = *inner_ty {
debug_assert!(matches!(
kind,
crate::ScalarKind::Sint | crate::ScalarKind::Uint
));
reconciled_id
kind
} else {
let component_type_id = self.get_type_id(LookupType::Local(LocalType::Value {
unreachable!("we only allow i32 and u32");
};
let cast = match (component_kind, array_index_kind) {
(crate::ScalarKind::Sint, crate::ScalarKind::Sint)
| (crate::ScalarKind::Uint, crate::ScalarKind::Uint) => None,
(crate::ScalarKind::Sint, crate::ScalarKind::Uint)
| (crate::ScalarKind::Uint, crate::ScalarKind::Sint) => Some(spirv::Op::Bitcast),
(crate::ScalarKind::Float, crate::ScalarKind::Sint) => Some(spirv::Op::ConvertSToF),
(crate::ScalarKind::Float, crate::ScalarKind::Uint) => Some(spirv::Op::ConvertUToF),
(crate::ScalarKind::Bool, _) => unreachable!("we don't allow bool for component"),
(_, crate::ScalarKind::Bool | crate::ScalarKind::Float) => {
unreachable!("we don't allow bool or float for array index")
}
};
let reconciled_array_index_id = if let Some(cast) = cast {
let component_ty_id = self.get_type_id(LookupType::Local(LocalType::Value {
vector_size: None,
kind: component_kind,
width: 4,
pointer_space: None,
}));

let reconciled_id = self.gen_id();
block.body.push(Instruction::unary(
spirv::Op::ConvertUToF,
component_type_id,
cast,
component_ty_id,
reconciled_id,
array_index_i32_id,
array_index_id,
));
reconciled_id
} else {
array_index_id
};

// Find the SPIR-V type for the combined coordinates/index vector.
Expand Down
4 changes: 2 additions & 2 deletions src/valid/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ impl super::Validator {
if let Some(expr) = array_index {
match resolver[expr] {
Ti::Scalar {
kind: Sk::Sint,
kind: Sk::Sint | Sk::Uint,
width: _,
} => {}
_ => return Err(ExpressionError::InvalidImageArrayIndexType(expr)),
Expand Down Expand Up @@ -548,7 +548,7 @@ impl super::Validator {
if let Some(expr) = array_index {
match resolver[expr] {
Ti::Scalar {
kind: Sk::Sint,
kind: Sk::Sint | Sk::Uint,
width: _,
} => {}
_ => return Err(ExpressionError::InvalidImageArrayIndexType(expr)),
Expand Down
2 changes: 1 addition & 1 deletion src/valid/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ impl super::Validator {
if let Some(expr) = array_index {
match *context.resolve_type(expr, &self.valid_expression_set)? {
Ti::Scalar {
kind: crate::ScalarKind::Sint,
kind: crate::ScalarKind::Sint | crate::ScalarKind::Uint,
width: _,
} => {}
_ => {
Expand Down
27 changes: 21 additions & 6 deletions tests/in/bounds-check-image-restrict.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ fn test_textureLoad_2d(coords: vec2<i32>, level: i32) -> vec4<f32> {
@group(0) @binding(2)
var image_2d_array: texture_2d_array<f32>;

fn test_textureLoad_2d_array(coords: vec2<i32>, index: i32, level: i32) -> vec4<f32> {
fn test_textureLoad_2d_array_u(coords: vec2<i32>, index: u32, level: i32) -> vec4<f32> {
return textureLoad(image_2d_array, coords, index, level);
}

fn test_textureLoad_2d_array_s(coords: vec2<i32>, index: i32, level: i32) -> vec4<f32> {
return textureLoad(image_2d_array, coords, index, level);
}

Expand Down Expand Up @@ -43,7 +47,11 @@ fn test_textureLoad_depth_2d(coords: vec2<i32>, level: i32) -> f32 {
@group(0) @binding(6)
var image_depth_2d_array: texture_depth_2d_array;

fn test_textureLoad_depth_2d_array(coords: vec2<i32>, index: i32, level: i32) -> f32 {
fn test_textureLoad_depth_2d_array_u(coords: vec2<i32>, index: u32, level: i32) -> f32 {
return textureLoad(image_depth_2d_array, coords, index, level);
}

fn test_textureLoad_depth_2d_array_s(coords: vec2<i32>, index: i32, level: i32) -> f32 {
return textureLoad(image_depth_2d_array, coords, index, level);
}

Expand Down Expand Up @@ -71,7 +79,11 @@ fn test_textureStore_2d(coords: vec2<i32>, value: vec4<f32>) {
@group(0) @binding(10)
var image_storage_2d_array: texture_storage_2d_array<rgba8unorm, write>;

fn test_textureStore_2d_array(coords: vec2<i32>, array_index: i32, value: vec4<f32>) {
fn test_textureStore_2d_array_u(coords: vec2<i32>, array_index: u32, value: vec4<f32>) {
textureStore(image_storage_2d_array, coords, array_index, value);
}

fn test_textureStore_2d_array_s(coords: vec2<i32>, array_index: i32, value: vec4<f32>) {
textureStore(image_storage_2d_array, coords, array_index, value);
}

Expand All @@ -88,16 +100,19 @@ fn test_textureStore_3d(coords: vec3<i32>, value: vec4<f32>) {
fn fragment_shader() -> @location(0) vec4<f32> {
test_textureLoad_1d(0, 0);
test_textureLoad_2d(vec2<i32>(), 0);
test_textureLoad_2d_array(vec2<i32>(), 0, 0);
test_textureLoad_2d_array_u(vec2<i32>(), 0u, 0);
test_textureLoad_2d_array_s(vec2<i32>(), 0, 0);
test_textureLoad_3d(vec3<i32>(), 0);
test_textureLoad_multisampled_2d(vec2<i32>(), 0);
// Not yet implemented for GLSL:
// test_textureLoad_depth_2d(vec2<i32>(), 0);
// test_textureLoad_depth_2d_array(vec2<i32>(), 0, 0);
// test_textureLoad_depth_2d_array_u(vec2<i32>(), 0u, 0);
// test_textureLoad_depth_2d_array_s(vec2<i32>(), 0, 0);
// test_textureLoad_depth_multisampled_2d(vec2<i32>(), 0);
test_textureStore_1d(0, vec4<f32>());
test_textureStore_2d(vec2<i32>(), vec4<f32>());
test_textureStore_2d_array(vec2<i32>(), 0, vec4<f32>());
test_textureStore_2d_array_u(vec2<i32>(), 0u, vec4<f32>());
test_textureStore_2d_array_s(vec2<i32>(), 0, vec4<f32>());
test_textureStore_3d(vec3<i32>(), vec4<f32>());

return vec4<f32>(0.,0.,0.,0.);
Expand Down
27 changes: 21 additions & 6 deletions tests/in/bounds-check-image-rzsw.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ fn test_textureLoad_2d(coords: vec2<i32>, level: i32) -> vec4<f32> {
@group(0) @binding(2)
var image_2d_array: texture_2d_array<f32>;

fn test_textureLoad_2d_array(coords: vec2<i32>, index: i32, level: i32) -> vec4<f32> {
fn test_textureLoad_2d_array_u(coords: vec2<i32>, index: u32, level: i32) -> vec4<f32> {
return textureLoad(image_2d_array, coords, index, level);
}

fn test_textureLoad_2d_array_s(coords: vec2<i32>, index: i32, level: i32) -> vec4<f32> {
return textureLoad(image_2d_array, coords, index, level);
}

Expand Down Expand Up @@ -43,7 +47,11 @@ fn test_textureLoad_depth_2d(coords: vec2<i32>, level: i32) -> f32 {
@group(0) @binding(6)
var image_depth_2d_array: texture_depth_2d_array;

fn test_textureLoad_depth_2d_array(coords: vec2<i32>, index: i32, level: i32) -> f32 {
fn test_textureLoad_depth_2d_array_u(coords: vec2<i32>, index: u32, level: i32) -> f32 {
return textureLoad(image_depth_2d_array, coords, index, level);
}

fn test_textureLoad_depth_2d_array_s(coords: vec2<i32>, index: i32, level: i32) -> f32 {
return textureLoad(image_depth_2d_array, coords, index, level);
}

Expand Down Expand Up @@ -71,7 +79,11 @@ fn test_textureStore_2d(coords: vec2<i32>, value: vec4<f32>) {
@group(0) @binding(10)
var image_storage_2d_array: texture_storage_2d_array<rgba8unorm, write>;

fn test_textureStore_2d_array(coords: vec2<i32>, array_index: i32, value: vec4<f32>) {
fn test_textureStore_2d_array_u(coords: vec2<i32>, array_index: u32, value: vec4<f32>) {
textureStore(image_storage_2d_array, coords, array_index, value);
}

fn test_textureStore_2d_array_s(coords: vec2<i32>, array_index: i32, value: vec4<f32>) {
textureStore(image_storage_2d_array, coords, array_index, value);
}

Expand All @@ -88,16 +100,19 @@ fn test_textureStore_3d(coords: vec3<i32>, value: vec4<f32>) {
fn fragment_shader() -> @location(0) vec4<f32> {
test_textureLoad_1d(0, 0);
test_textureLoad_2d(vec2<i32>(), 0);
test_textureLoad_2d_array(vec2<i32>(), 0, 0);
test_textureLoad_2d_array_u(vec2<i32>(), 0u, 0);
test_textureLoad_2d_array_s(vec2<i32>(), 0, 0);
test_textureLoad_3d(vec3<i32>(), 0);
test_textureLoad_multisampled_2d(vec2<i32>(), 0);
// Not yet implemented for GLSL:
// test_textureLoad_depth_2d(vec2<i32>(), 0);
// test_textureLoad_depth_2d_array(vec2<i32>(), 0, 0);
// test_textureLoad_depth_2d_array_u(vec2<i32>(), 0u, 0);
// test_textureLoad_depth_2d_array_s(vec2<i32>(), 0, 0);
// test_textureLoad_depth_multisampled_2d(vec2<i32>(), 0);
test_textureStore_1d(0, vec4<f32>());
test_textureStore_2d(vec2<i32>(), vec4<f32>());
test_textureStore_2d_array(vec2<i32>(), 0, vec4<f32>());
test_textureStore_2d_array_u(vec2<i32>(), 0u, vec4<f32>());
test_textureStore_2d_array_s(vec2<i32>(), 0, vec4<f32>());
test_textureStore_3d(vec3<i32>(), vec4<f32>());

return vec4<f32>(0.,0.,0.,0.);
Expand Down
59 changes: 44 additions & 15 deletions tests/in/image.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ fn main(@builtin(local_invocation_id) local_id: vec3<u32>) {
let value1 = textureLoad(image_mipmapped_src, itc, i32(local_id.z));
let value2 = textureLoad(image_multisampled_src, itc, i32(local_id.z));
let value4 = textureLoad(image_storage_src, itc);
let value5 = textureLoad(image_array_src, itc, i32(local_id.z), i32(local_id.z) + 1);
let value6 = textureLoad(image_1d_src, i32(local_id.x), i32(local_id.z));
let value5 = textureLoad(image_array_src, itc, local_id.z, i32(local_id.z) + 1);
let value6 = textureLoad(image_array_src, itc, i32(local_id.z), i32(local_id.z) + 1);
let value7 = textureLoad(image_1d_src, i32(local_id.x), i32(local_id.z));
// loads with uvec2 coords.
let value1u = textureLoad(image_mipmapped_src, vec2<u32>(itc), i32(local_id.z));
let value2u = textureLoad(image_multisampled_src, vec2<u32>(itc), i32(local_id.z));
let value4u = textureLoad(image_storage_src, vec2<u32>(itc));
let value5u = textureLoad(image_array_src, vec2<u32>(itc), i32(local_id.z), i32(local_id.z) + 1);
let value6u = textureLoad(image_1d_src, u32(local_id.x), i32(local_id.z));
let value5u = textureLoad(image_array_src, vec2<u32>(itc), local_id.z, i32(local_id.z) + 1);
let value6u = textureLoad(image_array_src, vec2<u32>(itc), i32(local_id.z), i32(local_id.z) + 1);
let value7u = textureLoad(image_1d_src, u32(local_id.x), i32(local_id.z));
// store with ivec2 coords.
textureStore(image_dst, itc.x, value1 + value2 + value4 + value5 + value6);
// store with uvec2 coords.
Expand Down Expand Up @@ -109,31 +111,58 @@ var sampler_reg: sampler;
@fragment
fn texture_sample() -> @location(0) vec4<f32> {
let tc = vec2<f32>(0.5);
let tc3 = vec3<f32>(0.5);
let level = 2.3;
let s1d = textureSample(image_1d, sampler_reg, tc.x);
let s2d = textureSample(image_2d, sampler_reg, tc);
let s2d_offset = textureSample(image_2d, sampler_reg, tc, vec2<i32>(3, 1));
let s2d_level = textureSampleLevel(image_2d, sampler_reg, tc, level);
let s2d_level_offset = textureSampleLevel(image_2d, sampler_reg, tc, level, vec2<i32>(3, 1));
let s2d_bias_offset = textureSampleBias(image_2d, sampler_reg, tc, 2.0, vec2<i32>(3, 1));
return s1d + s2d + s2d_offset + s2d_level + s2d_level_offset;
var a: vec4<f32>;
a += textureSample(image_1d, sampler_reg, tc.x);
a += textureSample(image_2d, sampler_reg, tc);
a += textureSample(image_2d, sampler_reg, tc, vec2<i32>(3, 1));
a += textureSampleLevel(image_2d, sampler_reg, tc, level);
a += textureSampleLevel(image_2d, sampler_reg, tc, level, vec2<i32>(3, 1));
a += textureSampleBias(image_2d, sampler_reg, tc, 2.0, vec2<i32>(3, 1));
a += textureSample(image_2d_array, sampler_reg, tc, 0u);
a += textureSample(image_2d_array, sampler_reg, tc, 0u, vec2<i32>(3, 1));
a += textureSampleLevel(image_2d_array, sampler_reg, tc, 0u, level);
a += textureSampleLevel(image_2d_array, sampler_reg, tc, 0u, level, vec2<i32>(3, 1));
a += textureSampleBias(image_2d_array, sampler_reg, tc, 0u, 2.0, vec2<i32>(3, 1));
a += textureSample(image_2d_array, sampler_reg, tc, 0);
a += textureSample(image_2d_array, sampler_reg, tc, 0, vec2<i32>(3, 1));
a += textureSampleLevel(image_2d_array, sampler_reg, tc, 0, level);
a += textureSampleLevel(image_2d_array, sampler_reg, tc, 0, level, vec2<i32>(3, 1));
a += textureSampleBias(image_2d_array, sampler_reg, tc, 0, 2.0, vec2<i32>(3, 1));
a += textureSample(image_cube_array, sampler_reg, tc3, 0u);
a += textureSampleLevel(image_cube_array, sampler_reg, tc3, 0u, level);
a += textureSampleBias(image_cube_array, sampler_reg, tc3, 0u, 2.0);
a += textureSample(image_cube_array, sampler_reg, tc3, 0);
a += textureSampleLevel(image_cube_array, sampler_reg, tc3, 0, level);
a += textureSampleBias(image_cube_array, sampler_reg, tc3, 0, 2.0);
return a;
}

@group(1) @binding(1)
var sampler_cmp: sampler_comparison;
@group(1) @binding(2)
var image_2d_depth: texture_depth_2d;
@group(1) @binding(3)
var image_2d_array_depth: texture_depth_2d_array;
@group(1) @binding(4)
var image_cube_depth: texture_depth_cube;

@fragment
fn texture_sample_comparison() -> @location(0) f32 {
let tc = vec2<f32>(0.5);
let tc3 = vec3<f32>(0.5);
let dref = 0.5;
let s2d_depth = textureSampleCompare(image_2d_depth, sampler_cmp, tc, dref);
let s2d_depth_level = textureSampleCompareLevel(image_2d_depth, sampler_cmp, tc, dref);
let scube_depth_level = textureSampleCompareLevel(image_cube_depth, sampler_cmp, vec3<f32>(0.5), dref);
return s2d_depth + s2d_depth_level;
var a: f32;
a += textureSampleCompare(image_2d_depth, sampler_cmp, tc, dref);
a += textureSampleCompare(image_2d_array_depth, sampler_cmp, tc, 0u, dref);
a += textureSampleCompare(image_2d_array_depth, sampler_cmp, tc, 0, dref);
a += textureSampleCompare(image_cube_depth, sampler_cmp, tc3, dref);
a += textureSampleCompareLevel(image_2d_depth, sampler_cmp, tc, dref);
a += textureSampleCompareLevel(image_2d_array_depth, sampler_cmp, tc, 0u, dref);
a += textureSampleCompareLevel(image_2d_array_depth, sampler_cmp, tc, 0, dref);
a += textureSampleCompareLevel(image_cube_depth, sampler_cmp, tc3, dref);
return a;
}

@fragment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,53 +32,66 @@ vec4 test_textureLoad_2d(ivec2 coords_1, int level_1) {
return _e3;
}

vec4 test_textureLoad_2d_array(ivec2 coords_2, int index, int level_2) {
vec4 test_textureLoad_2d_array_u(ivec2 coords_2, uint index, int level_2) {
int _e4_clamped_lod = clamp(level_2, 0, textureQueryLevels(_group_0_binding_2_fs) - 1);
vec4 _e4 = texelFetch(_group_0_binding_2_fs, clamp(ivec3(coords_2, index), ivec3(0), textureSize(_group_0_binding_2_fs, _e4_clamped_lod) - ivec3(1)), _e4_clamped_lod);
return _e4;
}

vec4 test_textureLoad_3d(ivec3 coords_3, int level_3) {
int _e3_clamped_lod = clamp(level_3, 0, textureQueryLevels(_group_0_binding_3_fs) - 1);
vec4 _e3 = texelFetch(_group_0_binding_3_fs, clamp(coords_3, ivec3(0), textureSize(_group_0_binding_3_fs, _e3_clamped_lod) - ivec3(1)), _e3_clamped_lod);
vec4 test_textureLoad_2d_array_s(ivec2 coords_3, int index_1, int level_3) {
int _e4_clamped_lod = clamp(level_3, 0, textureQueryLevels(_group_0_binding_2_fs) - 1);
vec4 _e4 = texelFetch(_group_0_binding_2_fs, clamp(ivec3(coords_3, index_1), ivec3(0), textureSize(_group_0_binding_2_fs, _e4_clamped_lod) - ivec3(1)), _e4_clamped_lod);
return _e4;
}

vec4 test_textureLoad_3d(ivec3 coords_4, int level_4) {
int _e3_clamped_lod = clamp(level_4, 0, textureQueryLevels(_group_0_binding_3_fs) - 1);
vec4 _e3 = texelFetch(_group_0_binding_3_fs, clamp(coords_4, ivec3(0), textureSize(_group_0_binding_3_fs, _e3_clamped_lod) - ivec3(1)), _e3_clamped_lod);
return _e3;
}

vec4 test_textureLoad_multisampled_2d(ivec2 coords_4, int _sample) {
vec4 _e3 = texelFetch(_group_0_binding_4_fs, clamp(coords_4, ivec2(0), textureSize(_group_0_binding_4_fs) - ivec2(1)), clamp(_sample, 0, textureSamples(_group_0_binding_4_fs) - 1)
vec4 test_textureLoad_multisampled_2d(ivec2 coords_5, int _sample) {
vec4 _e3 = texelFetch(_group_0_binding_4_fs, clamp(coords_5, ivec2(0), textureSize(_group_0_binding_4_fs) - ivec2(1)), clamp(_sample, 0, textureSamples(_group_0_binding_4_fs) - 1)
);
return _e3;
}

void test_textureStore_1d(int coords_8, vec4 value) {
imageStore(_group_0_binding_8_fs, coords_8, value);
void test_textureStore_1d(int coords_10, vec4 value) {
imageStore(_group_0_binding_8_fs, coords_10, value);
return;
}

void test_textureStore_2d(ivec2 coords_11, vec4 value_1) {
imageStore(_group_0_binding_9_fs, coords_11, value_1);
return;
}

void test_textureStore_2d(ivec2 coords_9, vec4 value_1) {
imageStore(_group_0_binding_9_fs, coords_9, value_1);
void test_textureStore_2d_array_u(ivec2 coords_12, uint array_index, vec4 value_2) {
imageStore(_group_0_binding_10_fs, ivec3(coords_12, array_index), value_2);
return;
}

void test_textureStore_2d_array(ivec2 coords_10, int array_index, vec4 value_2) {
imageStore(_group_0_binding_10_fs, ivec3(coords_10, array_index), value_2);
void test_textureStore_2d_array_s(ivec2 coords_13, int array_index_1, vec4 value_3) {
imageStore(_group_0_binding_10_fs, ivec3(coords_13, array_index_1), value_3);
return;
}

void test_textureStore_3d(ivec3 coords_11, vec4 value_3) {
imageStore(_group_0_binding_11_fs, coords_11, value_3);
void test_textureStore_3d(ivec3 coords_14, vec4 value_4) {
imageStore(_group_0_binding_11_fs, coords_14, value_4);
return;
}

void main() {
vec4 _e2 = test_textureLoad_1d(0, 0);
vec4 _e5 = test_textureLoad_2d(ivec2(0, 0), 0);
vec4 _e9 = test_textureLoad_2d_array(ivec2(0, 0), 0, 0);
vec4 _e12 = test_textureLoad_3d(ivec3(0, 0, 0), 0);
vec4 _e15 = test_textureLoad_multisampled_2d(ivec2(0, 0), 0);
vec4 _e9 = test_textureLoad_2d_array_u(ivec2(0, 0), 0u, 0);
vec4 _e13 = test_textureLoad_2d_array_s(ivec2(0, 0), 0, 0);
vec4 _e16 = test_textureLoad_3d(ivec3(0, 0, 0), 0);
vec4 _e19 = test_textureLoad_multisampled_2d(ivec2(0, 0), 0);
test_textureStore_1d(0, vec4(0.0, 0.0, 0.0, 0.0));
test_textureStore_2d(ivec2(0, 0), vec4(0.0, 0.0, 0.0, 0.0));
test_textureStore_2d_array(ivec2(0, 0), 0, vec4(0.0, 0.0, 0.0, 0.0));
test_textureStore_2d_array_u(ivec2(0, 0), 0u, vec4(0.0, 0.0, 0.0, 0.0));
test_textureStore_2d_array_s(ivec2(0, 0), 0, vec4(0.0, 0.0, 0.0, 0.0));
test_textureStore_3d(ivec3(0, 0, 0), vec4(0.0, 0.0, 0.0, 0.0));
_fs2p_location0 = vec4(0.0, 0.0, 0.0, 0.0);
return;
Expand Down
Loading

0 comments on commit f59668c

Please sign in to comment.