| 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); |
| }); |