Skip to content

Commit

Permalink
Cleanup texture builtin WGSL validation tests
Browse files Browse the repository at this point in the history
Also add in_fragment_only tests that tests these
builtins only work in the fragment shader.
  • Loading branch information
greggman committed Mar 14, 2024
1 parent 8cac6fe commit 83eda31
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 13 deletions.
2 changes: 2 additions & 0 deletions src/webgpu/listing_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -1944,11 +1944,13 @@
"webgpu:shader,validation,expression,call,builtin,textureSample:coords_argument:*": { "subcaseMS": 1.342 },
"webgpu:shader,validation,expression,call,builtin,textureSample:offset_argument,non_const:*": { "subcaseMS": 1.604 },
"webgpu:shader,validation,expression,call,builtin,textureSample:offset_argument:*": { "subcaseMS": 1.401 },
"webgpu:shader,validation,expression,call,builtin,textureSample:only_in_fragment:*": { "subcaseMS": 1.121 },
"webgpu:shader,validation,expression,call,builtin,textureSampleCompare:array_index_argument:*": { "subcaseMS": 1.932 },
"webgpu:shader,validation,expression,call,builtin,textureSampleCompare:coords_argument:*": { "subcaseMS": 1.282 },
"webgpu:shader,validation,expression,call,builtin,textureSampleCompare:depth_ref_argument:*": { "subcaseMS": 1.563 },
"webgpu:shader,validation,expression,call,builtin,textureSampleCompare:offset_argument,non_const:*": { "subcaseMS": 1.720 },
"webgpu:shader,validation,expression,call,builtin,textureSampleCompare:offset_argument:*": { "subcaseMS": 1.540 },
"webgpu:shader,validation,expression,call,builtin,textureSampleCompare:only_in_fragment:*": { "subcaseMS": 1.121 },
"webgpu:shader,validation,expression,call,builtin,unpack4xI8:bad_args:*": { "subcaseMS": 121.263 },
"webgpu:shader,validation,expression,call,builtin,unpack4xI8:must_use:*": { "subcaseMS": 35.200 },
"webgpu:shader,validation,expression,call,builtin,unpack4xI8:supported:*": { "subcaseMS": 24.150 },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Use to test that certain WGSL builtins are only available in the fragment stage.
* Create WGSL that defines a function "foo" and its required variables that uses
* the builtin being tested. Append it to these code strings then compile. It should
* succeed or fail based on the value `expectSuccess`.
*
* See ./textureSample.spec.ts was one example
*/
export const kEntryPointsToValidateFragmentOnlyBuiltins = {
none: {
expectSuccess: true,
code: ``,
},
fragment: {
expectSuccess: true,
code: `
@fragment
fn main() {
foo();
}
`,
},
vertex: {
expectSuccess: false,
code: `
@vertex
fn main() -> @builtin(position) vec4f {
foo();
return vec4f();
}
`,
},
compute: {
expectSuccess: false,
code: `
@compute @workgroup_size(1)
fn main() {
foo();
}
`,
},
fragment_and_compute: {
expectSuccess: false,
code: `
@fragment
fn main1() {
foo();
}
@compute @workgroup_size(1)
fn main2() {
foo();
}
`,
},
compute_without_call: {
expectSuccess: true,
code: `
@compute @workgroup_size(1)
fn main() {
}
`,
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Validation tests for the ${builtin}() builtin.
* test textureSample offset parameter must be correct type
* test textureSample offset parameter must be a const-expression
* test textureSample offset parameter must be between -8 and +7 inclusive
note: uniformity validation is covered in src/webgpu/shader/validation/uniformity/uniformity.spec.ts
`;

import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
Expand All @@ -22,6 +24,8 @@ import {
} from '../../../../../util/conversion.js';
import { ShaderValidationTest } from '../../../shader_validation_test.js';

import { kEntryPointsToValidateFragmentOnlyBuiltins } from './shader_stage_utils.js';

type TextureSampleArguments = {
coordsArgType: ScalarType | VectorType;
hasArrayIndexArg?: boolean;
Expand Down Expand Up @@ -55,6 +59,7 @@ const kValuesTypes = objectsToRecord(kAllScalarsAndVectors);
export const g = makeTestGroup(ShaderValidationTest);

g.test('coords_argument')
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesample')
.desc(
`
Validates that only incorrect coords arguments are rejected by ${builtin}
Expand All @@ -68,10 +73,9 @@ Validates that only incorrect coords arguments are rejected by ${builtin}
.combine('value', [-1, 0, 1] as const)
// filter out unsigned types with negative values
.filter(t => !isUnsignedType(kValuesTypes[t.coordType]) || t.value >= 0)
.expand('offset', ({ textureType }) => {
const offset = kValidTextureSampleParameterTypes[textureType].offsetArgType;
return offset ? [false, true] : [false];
})
.expand('offset', t =>
kValidTextureSampleParameterTypes[t.textureType].offsetArgType ? [false, true] : [false]
)
)
.fn(t => {
const { textureType, coordType, offset, value } = t.params;
Expand Down Expand Up @@ -99,6 +103,7 @@ Validates that only incorrect coords arguments are rejected by ${builtin}
});

g.test('array_index_argument')
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesample')
.desc(
`
Validates that only incorrect array_index arguments are rejected by ${builtin}
Expand All @@ -114,6 +119,9 @@ Validates that only incorrect array_index arguments are rejected by ${builtin}
.combine('value', [-9, -8, 0, 7, 8])
// filter out unsigned types with negative values
.filter(t => !isUnsignedType(kValuesTypes[t.arrayIndexType]) || t.value >= 0)
.expand('offset', t =>
kValidTextureSampleParameterTypes[t.textureType].offsetArgType ? [false, true] : [false]
)
)
.fn(t => {
const { textureType, arrayIndexType, value } = t.params;
Expand All @@ -139,6 +147,7 @@ Validates that only incorrect array_index arguments are rejected by ${builtin}
});

g.test('offset_argument')
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesample')
.desc(
`
Validates that only incorrect offset arguments are rejected by ${builtin}
Expand Down Expand Up @@ -183,6 +192,7 @@ Validates that only incorrect offset arguments are rejected by ${builtin}
});

g.test('offset_argument,non_const')
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesample')
.desc(
`
Validates that only non-const offset arguments are rejected by ${builtin}
Expand Down Expand Up @@ -218,3 +228,39 @@ Validates that only non-const offset arguments are rejected by ${builtin}
const expectSuccess = varType === 'c';
t.expectCompileResult(expectSuccess, code);
});

g.test('only_in_fragment')
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesample')
.desc(
`
Validates that ${builtin} must not be used in a compute or vertex shader.
`
)
.params(u =>
u
.combine('textureType', kTextureTypes)
.combine('entryPoint', keysOf(kEntryPointsToValidateFragmentOnlyBuiltins))
.expand('offset', t =>
kValidTextureSampleParameterTypes[t.textureType].offsetArgType ? [false, true] : [false]
)
)
.fn(t => {
const { textureType, entryPoint, offset } = t.params;
const { coordsArgType, hasArrayIndexArg, offsetArgType } =
kValidTextureSampleParameterTypes[textureType];

const coordWGSL = coordsArgType.create(0).wgsl();
const arrayWGSL = hasArrayIndexArg ? ', 0' : '';
const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : '';

const config = kEntryPointsToValidateFragmentOnlyBuiltins[entryPoint];
const code = `
${config.code}
@group(0) @binding(0) var s: sampler;
@group(0) @binding(1) var t: ${textureType};
fn foo() {
_ = textureSample(t, s, ${coordWGSL}${arrayWGSL}${offsetWGSL});
}`;
t.expectCompileResult(config.expectSuccess, code);
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Validation tests for the ${builtin}() builtin.
* test textureSampleCompare offset parameter must be correct type
* test textureSampleCompare offset parameter must be a const-expression
* test textureSampleCompare offset parameter must be between -8 and +7 inclusive
note: uniformity validation is covered in src/webgpu/shader/validation/uniformity/uniformity.spec.ts
`;

import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
Expand All @@ -22,6 +24,8 @@ import {
} from '../../../../../util/conversion.js';
import { ShaderValidationTest } from '../../../shader_validation_test.js';

import { kEntryPointsToValidateFragmentOnlyBuiltins } from './shader_stage_utils.js';

type TextureSampleCompareArguments = {
coordsArgType: ScalarType | VectorType;
hasArrayIndexArg?: boolean;
Expand All @@ -45,6 +49,7 @@ const kValuesTypes = objectsToRecord(kAllScalarsAndVectors);
export const g = makeTestGroup(ShaderValidationTest);

g.test('coords_argument')
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplecompare')
.desc(
`
Validates that only incorrect coords arguments are rejected by ${builtin}
Expand All @@ -58,10 +63,11 @@ Validates that only incorrect coords arguments are rejected by ${builtin}
.combine('value', [-1, 0, 1] as const)
// filter out unsigned types with negative values
.filter(t => !isUnsignedType(kValuesTypes[t.coordType]) || t.value >= 0)
.expand('offset', ({ textureType }) => {
const offset = kValidTextureSampleCompareParameterTypes[textureType].offsetArgType;
return offset ? [false, true] : [false];
})
.expand('offset', t =>
kValidTextureSampleCompareParameterTypes[t.textureType].offsetArgType
? [false, true]
: [false]
)
)
.fn(t => {
const { textureType, coordType, offset, value } = t.params;
Expand All @@ -80,7 +86,7 @@ Validates that only incorrect coords arguments are rejected by ${builtin}
@group(0) @binding(0) var s: sampler_comparison;
@group(0) @binding(1) var t: ${textureType};
@fragment fn fs() -> @location(0) vec4f {
let v = textureSampleCompare(t, s, ${coordWGSL}${arrayWGSL}, 0${offsetWGSL});
_ = textureSampleCompare(t, s, ${coordWGSL}${arrayWGSL}, 0${offsetWGSL});
return vec4f(0);
}
`;
Expand All @@ -89,6 +95,7 @@ Validates that only incorrect coords arguments are rejected by ${builtin}
});

g.test('array_index_argument')
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplecompare')
.desc(
`
Validates that only incorrect array_index arguments are rejected by ${builtin}
Expand All @@ -104,6 +111,11 @@ Validates that only incorrect array_index arguments are rejected by ${builtin}
.combine('value', [-9, -8, 0, 7, 8])
// filter out unsigned types with negative values
.filter(t => !isUnsignedType(kValuesTypes[t.arrayIndexType]) || t.value >= 0)
.expand('offset', t =>
kValidTextureSampleCompareParameterTypes[t.textureType].offsetArgType
? [false, true]
: [false]
)
)
.fn(t => {
const { textureType, arrayIndexType, value } = t.params;
Expand All @@ -119,7 +131,7 @@ Validates that only incorrect array_index arguments are rejected by ${builtin}
@group(0) @binding(0) var s: sampler_comparison;
@group(0) @binding(1) var t: ${textureType};
@fragment fn fs() -> @location(0) vec4f {
let v = textureSampleCompare(t, s, ${coordWGSL}, ${arrayWGSL}, 0${offsetWGSL});
_ = textureSampleCompare(t, s, ${coordWGSL}, ${arrayWGSL}, 0${offsetWGSL});
return vec4f(0);
}
`;
Expand All @@ -129,6 +141,7 @@ Validates that only incorrect array_index arguments are rejected by ${builtin}
});

g.test('depth_ref_argument')
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplecompare')
.desc(
`
Validates that only incorrect depth_ref arguments are rejected by ${builtin}
Expand All @@ -142,6 +155,11 @@ Validates that only incorrect depth_ref arguments are rejected by ${builtin}
.combine('value', [-1, 0, 1])
// filter out unsigned types with negative values
.filter(t => !isUnsignedType(kValuesTypes[t.depthRefType]) || t.value >= 0)
.expand('offset', t =>
kValidTextureSampleCompareParameterTypes[t.textureType].offsetArgType
? [false, true]
: [false]
)
)
.fn(t => {
const { textureType, depthRefType, value } = t.params;
Expand All @@ -159,7 +177,7 @@ Validates that only incorrect depth_ref arguments are rejected by ${builtin}
@group(0) @binding(0) var s: sampler_comparison;
@group(0) @binding(1) var t: ${textureType};
@fragment fn fs() -> @location(0) vec4f {
let v = textureSampleCompare(t, s, ${coordWGSL}${arrayWGSL}, ${depthRefWGSL}${offsetWGSL});
_ = textureSampleCompare(t, s, ${coordWGSL}${arrayWGSL}, ${depthRefWGSL}${offsetWGSL});
return vec4f(0);
}
`;
Expand All @@ -168,6 +186,7 @@ Validates that only incorrect depth_ref arguments are rejected by ${builtin}
});

g.test('offset_argument')
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplecompare')
.desc(
`
Validates that only incorrect offset arguments are rejected by ${builtin}
Expand Down Expand Up @@ -202,7 +221,7 @@ Validates that only incorrect offset arguments are rejected by ${builtin}
@group(0) @binding(0) var s: sampler_comparison;
@group(0) @binding(1) var t: ${textureType};
@fragment fn fs() -> @location(0) vec4f {
let v = textureSampleCompare(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL});
_ = textureSampleCompare(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL});
return vec4f(0);
}
`;
Expand All @@ -212,6 +231,7 @@ Validates that only incorrect offset arguments are rejected by ${builtin}
});

g.test('offset_argument,non_const')
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesamplecompare')
.desc(
`
Validates that only non-const offset arguments are rejected by ${builtin}
Expand Down Expand Up @@ -240,10 +260,48 @@ Validates that only non-const offset arguments are rejected by ${builtin}
@fragment fn fs() -> @location(0) vec4f {
const c = 1;
let l = ${offsetArgType?.create(0).wgsl()};
let v = textureSampleCompare(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL});
_ = textureSampleCompare(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL});
return vec4f(0);
}
`;
const expectSuccess = varType === 'c';
t.expectCompileResult(expectSuccess, code);
});

g.test('only_in_fragment')
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#texturesample')
.desc(
`
Validates that ${builtin} must not be used in a compute or vertex shader.
`
)
.params(u =>
u
.combine('textureType', kTextureTypes)
.combine('entryPoint', keysOf(kEntryPointsToValidateFragmentOnlyBuiltins))
.expand('offset', t =>
kValidTextureSampleCompareParameterTypes[t.textureType].offsetArgType
? [false, true]
: [false]
)
)
.fn(t => {
const { textureType, entryPoint, offset } = t.params;
const { coordsArgType, hasArrayIndexArg, offsetArgType } =
kValidTextureSampleCompareParameterTypes[textureType];

const coordWGSL = coordsArgType.create(0).wgsl();
const arrayWGSL = hasArrayIndexArg ? ', 0' : '';
const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : '';

const config = kEntryPointsToValidateFragmentOnlyBuiltins[entryPoint];
const code = `
${config.code}
@group(0) @binding(0) var s: sampler_comparison;
@group(0) @binding(1) var t: ${textureType};
fn foo() {
_ = textureSampleCompare(t, s, ${coordWGSL}${arrayWGSL}, 0${offsetWGSL});
}`;
t.expectCompileResult(config.expectSuccess, code);
});

0 comments on commit 83eda31

Please sign in to comment.