blob: 0a55d612cc0a37a44bd5306907b5b2451923cd36 [file] [log] [blame]
export const description = `Validation tests for identifiers`;
import { makeTestGroup } from '../../../../common/framework/test_group.js';
import { keysOf } from '../../../../common/util/data_tables.js';
import { ShaderValidationTest } from '../shader_validation_test.js';
export const g = makeTestGroup(ShaderValidationTest);
g.test('function_param')
.desc(
`Test that a function param can shadow a builtin, but the builtin is available for other params.`
)
.fn(t => {
const code = `
fn f(f: i32, i32: i32, t: i32) -> i32 { return i32; }
`;
t.expectCompileResult(true, code);
});
const kTests = {
abs: {
keyword: `abs`,
src: `_ = abs(1);`,
},
acos: {
keyword: `acos`,
src: `_ = acos(.2);`,
},
acosh: {
keyword: `acosh`,
src: `_ = acosh(1.2);`,
},
all: {
keyword: `all`,
src: `_ = all(true);`,
},
any: {
keyword: `any`,
src: `_ = any(true);`,
},
array_templated: {
keyword: `array`,
src: `_ = array<i32, 2>(1, 2);`,
},
array: {
keyword: `array`,
src: `_ = array(1, 2);`,
},
array_length: {
keyword: `arrayLength`,
src: `_ = arrayLength(&placeholder.rt_arr);`,
},
asin: {
keyword: `asin`,
src: `_ = asin(.2);`,
},
asinh: {
keyword: `asinh`,
src: `_ = asinh(1.2);`,
},
atan: {
keyword: `atan`,
src: `_ = atan(1.2);`,
},
atanh: {
keyword: `atanh`,
src: `_ = atanh(.2);`,
},
atan2: {
keyword: `atan2`,
src: `_ = atan2(1.2, 2.3);`,
},
bool: {
keyword: `bool`,
src: `_ = bool(1);`,
},
bitcast: {
keyword: `bitcast`,
src: `_ = bitcast<f32>(1i);`,
},
ceil: {
keyword: `ceil`,
src: `_ = ceil(1.23);`,
},
clamp: {
keyword: `clamp`,
src: `_ = clamp(1, 2, 3);`,
},
cos: {
keyword: `cos`,
src: `_ = cos(2);`,
},
cosh: {
keyword: `cosh`,
src: `_ = cosh(2.2);`,
},
countLeadingZeros: {
keyword: `countLeadingZeros`,
src: `_ = countLeadingZeros(1);`,
},
countOneBits: {
keyword: `countOneBits`,
src: `_ = countOneBits(1);`,
},
countTrailingZeros: {
keyword: `countTrailingZeros`,
src: `_ = countTrailingZeros(1);`,
},
cross: {
keyword: `cross`,
src: `_ = cross(vec3(1, 2, 3), vec3(4, 5, 6));`,
},
degrees: {
keyword: `degrees`,
src: `_ = degrees(1);`,
},
determinant: {
keyword: `determinant`,
src: `_ = determinant(mat2x2(1, 2, 3, 4));`,
},
distance: {
keyword: `distance`,
src: `_ = distance(1, 2);`,
},
dot: {
keyword: `dot`,
src: `_ = dot(vec2(1, 2,), vec2(2, 3));`,
},
dot4U8Packed: {
keyword: `dot4U8Packed`,
src: `_ = dot4U8Packed(1, 2);`,
},
dot4I8Packed: {
keyword: `dot4I8Packed`,
src: `_ = dot4I8Packed(1, 2);`,
},
dpdx: {
keyword: `dpdx`,
src: `_ = dpdx(2);`,
},
dpdxCoarse: {
keyword: `dpdxCoarse`,
src: `_ = dpdxCoarse(2);`,
},
dpdxFine: {
keyword: `dpdxFine`,
src: `_ = dpdxFine(2);`,
},
dpdy: {
keyword: `dpdy`,
src: `_ = dpdy(2);`,
},
dpdyCoarse: {
keyword: `dpdyCoarse`,
src: `_ = dpdyCoarse(2);`,
},
dpdyFine: {
keyword: `dpdyFine`,
src: `_ = dpdyFine(2);`,
},
exp: {
keyword: `exp`,
src: `_ = exp(1);`,
},
exp2: {
keyword: `exp2`,
src: `_ = exp2(2);`,
},
extractBits: {
keyword: `extractBits`,
src: `_ = extractBits(1, 2, 3);`,
},
f32: {
keyword: `f32`,
src: `_ = f32(1i);`,
},
faceForward: {
keyword: `faceForward`,
src: `_ = faceForward(vec2(1, 2), vec2(3, 4), vec2(5, 6));`,
},
firstLeadingBit: {
keyword: `firstLeadingBit`,
src: `_ = firstLeadingBit(1);`,
},
firstTrailingBit: {
keyword: `firstTrailingBit`,
src: `_ = firstTrailingBit(1);`,
},
floor: {
keyword: `floor`,
src: `_ = floor(1.2);`,
},
fma: {
keyword: `fma`,
src: `_ = fma(1, 2, 3);`,
},
fract: {
keyword: `fract`,
src: `_ = fract(1);`,
},
frexp: {
keyword: `frexp`,
src: `_ = frexp(1);`,
},
fwidth: {
keyword: `fwidth`,
src: `_ = fwidth(2);`,
},
fwidthCoarse: {
keyword: `fwidthCoarse`,
src: `_ = fwidthCoarse(2);`,
},
fwidthFine: {
keyword: `fwidthFine`,
src: `_ = fwidthFine(2);`,
},
i32: {
keyword: `i32`,
src: `_ = i32(2u);`,
},
insertBits: {
keyword: `insertBits`,
src: `_ = insertBits(1, 2, 3, 4);`,
},
inverseSqrt: {
keyword: `inverseSqrt`,
src: `_ = inverseSqrt(1);`,
},
ldexp: {
keyword: `ldexp`,
src: `_ = ldexp(1, 2);`,
},
length: {
keyword: `length`,
src: `_ = length(1);`,
},
log: {
keyword: `log`,
src: `_ = log(2);`,
},
log2: {
keyword: `log2`,
src: `_ = log2(2);`,
},
mat2x2_templated: {
keyword: `mat2x2`,
src: `_ = mat2x2<f32>(1, 2, 3, 4);`,
},
mat2x2: {
keyword: `mat2x2`,
src: `_ = mat2x2(1, 2, 3, 4);`,
},
mat2x3_templated: {
keyword: `mat2x3`,
src: `_ = mat2x3<f32>(1, 2, 3, 4, 5, 6);`,
},
mat2x3: {
keyword: `mat2x3`,
src: `_ = mat2x3(1, 2, 3, 4, 5, 6);`,
},
mat2x4_templated: {
keyword: `mat2x4`,
src: `_ = mat2x4<f32>(1, 2, 3, 4, 5, 6, 7, 8);`,
},
mat2x4: {
keyword: `mat2x4`,
src: `_ = mat2x4(1, 2, 3, 4, 5, 6, 7, 8);`,
},
mat3x2_templated: {
keyword: `mat3x2`,
src: `_ = mat3x2<f32>(1, 2, 3, 4, 5, 6);`,
},
mat3x2: {
keyword: `mat3x2`,
src: `_ = mat3x2(1, 2, 3, 4, 5, 6);`,
},
mat3x3_templated: {
keyword: `mat3x3`,
src: `_ = mat3x3<f32>(1, 2, 3, 4, 5, 6, 7, 8, 9);`,
},
mat3x3: {
keyword: `mat3x3`,
src: `_ = mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9);`,
},
mat3x4_templated: {
keyword: `mat3x4`,
src: `_ = mat3x4<f32>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);`,
},
mat3x4: {
keyword: `mat3x4`,
src: `_ = mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);`,
},
mat4x2_templated: {
keyword: `mat4x2`,
src: `_ = mat4x2<f32>(1, 2, 3, 4, 5, 6, 7, 8);`,
},
mat4x2: {
keyword: `mat4x2`,
src: `_ = mat4x2(1, 2, 3, 4, 5, 6, 7, 8);`,
},
mat4x3_templated: {
keyword: `mat4x3`,
src: `_ = mat4x3<f32>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);`,
},
mat4x3: {
keyword: `mat4x3`,
src: `_ = mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);`,
},
mat4x4_templated: {
keyword: `mat4x4`,
src: `_ = mat4x4<f32>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);`,
},
mat4x4: {
keyword: `mat4x4`,
src: `_ = mat4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);`,
},
max: {
keyword: `max`,
src: `_ = max(1, 2);`,
},
min: {
keyword: `min`,
src: `_ = min(1, 2);`,
},
mix: {
keyword: `mix`,
src: `_ = mix(1, 2, 3);`,
},
modf: {
keyword: `modf`,
src: `_ = modf(1.2);`,
},
normalize: {
keyword: `normalize`,
src: `_ = normalize(vec2(1, 2));`,
},
pack2x16snorm: {
keyword: `pack2x16snorm`,
src: `_ = pack2x16snorm(vec2(1, 2));`,
},
pack2x16unorm: {
keyword: `pack2x16unorm`,
src: `_ = pack2x16unorm(vec2(1, 2));`,
},
pack2x16float: {
keyword: `pack2x16float`,
src: `_ = pack2x16float(vec2(1, 2));`,
},
pack4x8snorm: {
keyword: `pack4x8snorm`,
src: `_ = pack4x8snorm(vec4(1, 2, 3, 4));`,
},
pack4x8unorm: {
keyword: `pack4x8unorm`,
src: `_ = pack4x8unorm(vec4(1, 2, 3, 4));`,
},
pack4xI8: {
keyword: `pack4xI8`,
src: `_ = pack4xI8(vec4(1, 2, 3, 4));`,
},
pack4xU8: {
keyword: `pack4xU8`,
src: `_ = pack4xU8(vec4(1, 2, 3, 4));`,
},
pack4xI8Clamp: {
keyword: `pack4xI8Clamp`,
src: `_ = pack4xI8Clamp(vec4(1, 2, 3, 4));`,
},
pack4xU8Clamp: {
keyword: `pack4xU8Clamp`,
src: `_ = pack4xU8Clamp(vec4(1, 2, 3, 4));`,
},
pow: {
keyword: `pow`,
src: `_ = pow(1, 2);`,
},
quantizeToF16: {
keyword: `quantizeToF16`,
src: `_ = quantizeToF16(1.2);`,
},
radians: {
keyword: `radians`,
src: `_ = radians(1.2);`,
},
reflect: {
keyword: `reflect`,
src: `_ = reflect(vec2(1, 2), vec2(3, 4));`,
},
refract: {
keyword: `refract`,
src: `_ = refract(vec2(1, 1), vec2(2, 2), 3);`,
},
reverseBits: {
keyword: `reverseBits`,
src: `_ = reverseBits(1);`,
},
round: {
keyword: `round`,
src: `_ = round(1.2);`,
},
saturate: {
keyword: `saturate`,
src: `_ = saturate(1);`,
},
select: {
keyword: `select`,
src: `_ = select(1, 2, false);`,
},
sign: {
keyword: `sign`,
src: `_ = sign(1);`,
},
sin: {
keyword: `sin`,
src: `_ = sin(2);`,
},
sinh: {
keyword: `sinh`,
src: `_ = sinh(3);`,
},
smoothstep: {
keyword: `smoothstep`,
src: `_ = smoothstep(1, 2, 3);`,
},
sqrt: {
keyword: `sqrt`,
src: `_ = sqrt(24);`,
},
step: {
keyword: `step`,
src: `_ = step(4, 5);`,
},
tan: {
keyword: `tan`,
src: `_ = tan(2);`,
},
tanh: {
keyword: `tanh`,
src: `_ = tanh(2);`,
},
transpose: {
keyword: `transpose`,
src: `_ = transpose(mat2x2(1, 2, 3, 4));`,
},
trunc: {
keyword: `trunc`,
src: `_ = trunc(2);`,
},
u32: {
keyword: `u32`,
src: `_ = u32(1i);`,
},
unpack2x16snorm: {
keyword: `unpack2x16snorm`,
src: `_ = unpack2x16snorm(2);`,
},
unpack2x16unorm: {
keyword: `unpack2x16unorm`,
src: `_ = unpack2x16unorm(2);`,
},
unpack2x16float: {
keyword: `unpack2x16float`,
src: `_ = unpack2x16float(2);`,
},
unpack4x8snorm: {
keyword: `unpack4x8snorm`,
src: `_ = unpack4x8snorm(4);`,
},
unpack4x8unorm: {
keyword: `unpack4x8unorm`,
src: `_ = unpack4x8unorm(4);`,
},
unpack4xI8: {
keyword: `unpack4xI8`,
src: `_ = unpack4xI8(4);`,
},
unpack4xU8: {
keyword: `unpack4xU8`,
src: `_ = unpack4xU8(4);`,
},
vec2_templated: {
keyword: `vec2`,
src: `_ = vec2<f32>(1, 2);`,
},
vec2: {
keyword: `vec2`,
src: `_ = vec2(1, 2);`,
},
vec3_templated: {
keyword: `vec3`,
src: `_ = vec3<f32>(1, 2, 3);`,
},
vec3: {
keyword: `vec3`,
src: `_ = vec3(1, 2, 3);`,
},
vec4_templated: {
keyword: `vec4`,
src: `_ = vec4<f32>(1, 2, 3, 4);`,
},
vec4: {
keyword: `vec4`,
src: `_ = vec4(1, 2, 3, 4);`,
},
};
g.test('shadow_hides_builtin')
.desc(`Test that shadows hide builtins.`)
.params(u =>
u
.combine('inject', ['none', 'function', 'sibling', 'module'] as const)
.beginSubcases()
.combine('builtin', keysOf(kTests))
)
.fn(t => {
const data = kTests[t.params.builtin];
const local = `let ${data.keyword} = 4;`;
const module_shadow = t.params.inject === 'module' ? `var<private> ${data.keyword} : i32;` : ``;
const sibling_func = t.params.inject === 'sibling' ? local : ``;
const func = t.params.inject === 'function' ? local : ``;
const code = `
struct Data {
rt_arr: array<i32>,
}
@group(0) @binding(0) var<storage> placeholder: Data;
${module_shadow}
fn sibling() {
${sibling_func}
}
@fragment
fn main() -> @location(0) vec4f {
${func}
${data.src}
return vec4f(1);
}
`;
const pass = t.params.inject === 'none' || t.params.inject === 'sibling';
t.expectCompileResult(pass, code);
});
const kFloat16Tests = {
f16: {
keyword: `f16`,
src: `_ = f16(2);`,
},
};
g.test('shadow_hides_builtin_f16')
.desc(`Test that shadows hide builtins when shader-f16 is enabled.`)
.params(u =>
u
.combine('inject', ['none', 'function', 'sibling', 'module'] as const)
.beginSubcases()
.combine('builtin', keysOf(kFloat16Tests))
)
.fn(t => {
const data = kFloat16Tests[t.params.builtin];
const local = `let ${data.keyword} = 4;`;
const module_shadow = t.params.inject === 'module' ? `var<private> ${data.keyword} : f16;` : ``;
const sibling_func = t.params.inject === 'sibling' ? local : ``;
const func = t.params.inject === 'function' ? local : ``;
const code = `
enable f16;
${module_shadow}
fn sibling() {
${sibling_func}
}
@vertex
fn vtx() -> @builtin(position) vec4f {
${func}
${data.src}
return vec4f(1);
}
`;
const pass = t.params.inject === 'none' || t.params.inject === 'sibling';
t.expectCompileResult(pass, code);
});
const kTextureTypeTests = {
texture_1d: {
keyword: `texture_1d`,
src: `var t: texture_1d<f32>;`,
},
texture_2d: {
keyword: `texture_2d`,
src: `var t: texture_2d<f32>;`,
},
texture_2d_array: {
keyword: `texture_2d_array`,
src: `var t: texture_2d_array<f32>;`,
},
texture_3d: {
keyword: `texture_3d`,
src: `var t: texture_3d<f32>;`,
},
texture_cube: {
keyword: `texture_cube`,
src: `var t: texture_cube<f32>;`,
},
texture_cube_array: {
keyword: `texture_cube_array`,
src: `var t: texture_cube_array<f32>;`,
},
texture_multisampled_2d: {
keyword: `texture_multisampled_2d`,
src: `var t: texture_multisampled_2d<f32>;`,
},
texture_depth_multisampled_2d: {
keyword: `texture_depth_multisampled_2d`,
src: `var t: texture_depth_multisampled_2d;`,
},
texture_external: {
keyword: `texture_external`,
src: `var t: texture_external;`,
},
texture_storage_1d: {
keyword: `texture_storage_1d`,
src: `var t: texture_storage_1d<rgba8unorm, read_write>;`,
},
texture_storage_2d: {
keyword: `texture_storage_2d`,
src: `var t: texture_storage_2d<rgba8unorm, read_write>;`,
},
texture_storage_2d_array: {
keyword: `texture_storage_2d_array`,
src: `var t: texture_storage_2d_array<rgba8unorm, read_write>;`,
},
texture_storage_3d: {
keyword: `texture_storage_3d`,
src: `var t: texture_storage_3d<rgba8unorm, read_write>;`,
},
texture_depth_2d: {
keyword: `texture_depth_2d`,
src: `var t: texture_depth_2d;`,
},
texture_depth_2d_array: {
keyword: `texture_depth_2d_array`,
src: `var t: texture_depth_2d_array;`,
},
texture_depth_cube: {
keyword: `texture_depth_cube`,
src: `var t: texture_depth_cube;`,
},
texture_depth_cube_array: {
keyword: `texture_depth_cube_array`,
src: `var t: texture_depth_cube_array;`,
},
sampler: {
keyword: `sampler`,
src: `var s: sampler;`,
},
sampler_comparison: {
keyword: `sampler_comparison`,
src: `var s: sampler_comparison;`,
},
};
g.test('shadow_hides_builtin_handle_type')
.desc(`Test that shadows hide builtins when handle address space types are used.`)
.params(u =>
u
.combine('inject', ['none', 'function', 'module'] as const)
.beginSubcases()
.combine('builtin', keysOf(kTextureTypeTests))
)
.fn(t => {
const data = kTextureTypeTests[t.params.builtin];
const local = `let ${data.keyword} = 4;`;
const module_shadow = t.params.inject === 'module' ? `var<private> ${data.keyword} : f32;` : ``;
const func = t.params.inject === 'function' ? local : ``;
const code = `
${module_shadow}
@group(0) @binding(0) ${data.src}
fn func() {
${func}
}
`;
const pass = t.params.inject === 'none' || t.params.inject === 'function';
t.expectCompileResult(pass, code);
});
const kTextureTests = {
textureDimensions: {
keyword: `textureDimensions`,
src: `_ = textureDimensions(t_2d);`,
},
textureGather: {
keyword: `textureGather`,
src: `_ = textureGather(1, t_2d, s, vec2(1, 2));`,
},
textureGatherCompare: {
keyword: `textureGatherCompare`,
src: `_ = textureGatherCompare(t_2d_depth, sc, vec2(1, 2), 3);`,
},
textureLoad: {
keyword: `textureLoad`,
src: `_ = textureLoad(t_2d, vec2(1, 2), 1);`,
},
textureNumLayers: {
keyword: `textureNumLayers`,
src: `_ = textureNumLayers(t_2d_array);`,
},
textureNumLevels: {
keyword: `textureNumLevels`,
src: `_ = textureNumLevels(t_2d);`,
},
textureNumSamples: {
keyword: `textureNumSamples`,
src: `_ = textureNumSamples(t_2d_ms);`,
},
textureSample: {
keyword: `textureSample`,
src: `_ = textureSample(t_2d, s, vec2(1, 2));`,
},
textureSampleBias: {
keyword: `textureSampleBias`,
src: `_ = textureSampleBias(t_2d, s, vec2(1, 2), 2);`,
},
textureSampleCompare: {
keyword: `textureSampleCompare`,
src: `_ = textureSampleCompare(t_2d_depth, sc, vec2(1, 2), 2);`,
},
textureSampleCompareLevel: {
keyword: `textureSampleCompareLevel`,
src: `_ = textureSampleCompareLevel(t_2d_depth, sc, vec2(1, 2), 3, vec2(1, 2));`,
},
textureSampleGrad: {
keyword: `textureSampleGrad`,
src: `_ = textureSampleGrad(t_2d, s, vec2(1, 2), vec2(1, 2), vec2(1, 2));`,
},
textureSampleLevel: {
keyword: `textureSampleLevel`,
src: `_ = textureSampleLevel(t_2d, s, vec2(1, 2), 3);`,
},
textureSampleBaseClampToEdge: {
keyword: `textureSampleBaseClampToEdge`,
src: `_ = textureSampleBaseClampToEdge(t_2d, s, vec2(1, 2));`,
},
};
g.test('shadow_hides_builtin_texture')
.desc(`Test that shadows hide texture builtins.`)
.params(u =>
u
.combine('inject', ['none', 'function', 'sibling', 'module'] as const)
.beginSubcases()
.combine('builtin', keysOf(kTextureTests))
)
.fn(t => {
const data = kTextureTests[t.params.builtin];
const local = `let ${data.keyword} = 4;`;
const module_shadow = t.params.inject === 'module' ? `var<private> ${data.keyword} : i32;` : ``;
const sibling_func = t.params.inject === 'sibling' ? local : ``;
const func = t.params.inject === 'function' ? local : ``;
const code = `
@group(0) @binding(0) var t_2d: texture_2d<f32>;
@group(0) @binding(1) var t_2d_depth: texture_depth_2d;
@group(0) @binding(2) var t_2d_array: texture_2d_array<f32>;
@group(0) @binding(3) var t_2d_ms: texture_multisampled_2d<f32>;
@group(1) @binding(0) var s: sampler;
@group(1) @binding(1) var sc: sampler_comparison;
${module_shadow}
fn sibling() {
${sibling_func}
}
@fragment
fn main() -> @location(0) vec4f {
${func}
${data.src}
return vec4f(1);
}
`;
const pass = t.params.inject === 'none' || t.params.inject === 'sibling';
t.expectCompileResult(pass, code);
});
g.test('shadow_hides_builtin_atomic_type')
.desc(`Test that shadows hide builtins when atomic types are used.`)
.params(u => u.combine('inject', ['none', 'function', 'module'] as const).beginSubcases())
.fn(t => {
const local = `let atomic = 4;`;
const module_shadow = t.params.inject === 'module' ? `var<private> atomic: i32;` : ``;
const func = t.params.inject === 'function' ? local : ``;
const code = `
${module_shadow}
var<workgroup> val: atomic<i32>;
fn func() {
${func}
}
`;
const pass = t.params.inject === 'none' || t.params.inject === 'function';
t.expectCompileResult(pass, code);
});
const kAtomicTests = {
atomicLoad: {
keyword: `atomicLoad`,
src: `_ = atomicLoad(&a);`,
},
atomicStore: {
keyword: `atomicStore`,
src: `atomicStore(&a, 1);`,
},
atomicAdd: {
keyword: `atomicAdd`,
src: `_ = atomicAdd(&a, 1);`,
},
atomicSub: {
keyword: `atomicSub`,
src: `_ = atomicSub(&a, 1);`,
},
atomicMax: {
keyword: `atomicMax`,
src: `_ = atomicMax(&a, 1);`,
},
atomicMin: {
keyword: `atomicMin`,
src: `_ = atomicMin(&a, 1);`,
},
atomicAnd: {
keyword: `atomicAnd`,
src: `_ = atomicAnd(&a, 1);`,
},
atomicOr: {
keyword: `atomicOr`,
src: `_ = atomicOr(&a, 1);`,
},
atomicXor: {
keyword: `atomicXor`,
src: `_ = atomicXor(&a, 1);`,
},
};
g.test('shadow_hides_builtin_atomic')
.desc(`Test that shadows hide builtin atomic methods.`)
.params(u =>
u
.combine('inject', ['none', 'function', 'sibling', 'module'] as const)
.beginSubcases()
.combine('builtin', keysOf(kAtomicTests))
)
.fn(t => {
const data = kAtomicTests[t.params.builtin];
const local = `let ${data.keyword} = 4;`;
const module_shadow = t.params.inject === 'module' ? `var<private> ${data.keyword} : i32;` : ``;
const sibling_func = t.params.inject === 'sibling' ? local : ``;
const func = t.params.inject === 'function' ? local : ``;
const code = `
var<workgroup> a: atomic<i32>;
${module_shadow}
fn sibling() {
${sibling_func}
}
@compute @workgroup_size(1)
fn main() {
${func}
${data.src}
}
`;
const pass = t.params.inject === 'none' || t.params.inject === 'sibling';
t.expectCompileResult(pass, code);
});
const kBarrierTests = {
storageBarrier: {
keyword: `storageBarrier`,
src: `storageBarrier();`,
},
textureBarrier: {
keyword: `textureBarrier`,
src: `textureBarrier();`,
},
workgroupBarrier: {
keyword: `workgroupBarrier`,
src: `workgroupBarrier();`,
},
workgroupUniformLoad: {
keyword: `workgroupUniformLoad`,
src: `_ = workgroupUniformLoad(&u);`,
},
};
g.test('shadow_hides_builtin_barriers')
.desc(`Test that shadows hide builtin barrier methods.`)
.params(u =>
u
.combine('inject', ['none', 'function', 'sibling', 'module'] as const)
.beginSubcases()
.combine('builtin', keysOf(kBarrierTests))
)
.fn(t => {
const data = kBarrierTests[t.params.builtin];
const local = `let ${data.keyword} = 4;`;
const module_shadow = t.params.inject === 'module' ? `var<private> ${data.keyword} : i32;` : ``;
const sibling_func = t.params.inject === 'sibling' ? local : ``;
const func = t.params.inject === 'function' ? local : ``;
const code = `
var<workgroup> u: u32;
${module_shadow}
fn sibling() {
${sibling_func}
}
@compute @workgroup_size(1)
fn main() {
${func}
${data.src}
}
`;
const pass = t.params.inject === 'none' || t.params.inject === 'sibling';
t.expectCompileResult(pass, code);
});
const kAccessModeTests = {
read: {
keyword: `read`,
src: `var<storage, read> a: i32;`,
},
read_write: {
keyword: `read_write`,
src: `var<storage, read_write> a: i32;`,
},
write: {
keyword: `write`,
src: `var t: texture_storage_1d<rgba8unorm, write>;`,
},
};
g.test('shadow_hides_access_mode')
.desc(`Test that shadows hide access modes.`)
.params(u =>
u
.combine('inject', ['none', 'function', 'module'] as const)
.beginSubcases()
.combine('builtin', keysOf(kAccessModeTests))
)
.fn(t => {
const data = kAccessModeTests[t.params.builtin];
const local = `let ${data.keyword} = 4;`;
const module_shadow = t.params.inject === 'module' ? `var<private> ${data.keyword} : i32;` : ``;
const func = t.params.inject === 'function' ? local : ``;
const code = `
${module_shadow}
@group(0) @binding(0) ${data.src}
@compute @workgroup_size(1)
fn main() {
${func}
}
`;
const pass = t.params.inject === 'none' || t.params.inject === 'function';
t.expectCompileResult(pass, code);
});