Skip to content

Commit

Permalink
wgsl: Add tests for requires directives (#3315)
Browse files Browse the repository at this point in the history
Includes some updates to other directive tests to cover directive
ordering constraints.

Fixes #2317
  • Loading branch information
jrprice authored Jan 25, 2024
1 parent 462fd8e commit 66ef471
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 2 deletions.
5 changes: 5 additions & 0 deletions src/webgpu/listing_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -1876,6 +1876,7 @@
"webgpu:shader,validation,parse,comments:unterminated_block_comment:*": { "subcaseMS": 8.950 },
"webgpu:shader,validation,parse,const:placement:*": { "subcaseMS": 1.167 },
"webgpu:shader,validation,parse,const_assert:parse:*": { "subcaseMS": 1.400 },
"webgpu:shader,validation,parse,diagnostic:after_other_directives:*": { "subcaseMS": 1.000 },
"webgpu:shader,validation,parse,diagnostic:conflicting_attribute_different_location:*": { "subcaseMS": 2.257 },
"webgpu:shader,validation,parse,diagnostic:conflicting_attribute_same_location:*": { "subcaseMS": 1.400 },
"webgpu:shader,validation,parse,diagnostic:conflicting_directive:*": { "subcaseMS": 1.244 },
Expand Down Expand Up @@ -1916,6 +1917,8 @@
"webgpu:shader,validation,parse,pipeline_stage:multiple_entry_points:*": { "subcaseMS": 1.100 },
"webgpu:shader,validation,parse,pipeline_stage:placement:*": { "subcaseMS": 1.388 },
"webgpu:shader,validation,parse,pipeline_stage:vertex_parsing:*": { "subcaseMS": 1.500 },
"webgpu:shader,validation,parse,requires:requires:*": { "subcaseMS": 1.000 },
"webgpu:shader,validation,parse,requires:wgsl_matches_api:*": { "subcaseMS": 1.000 },
"webgpu:shader,validation,parse,semicolon:after_assignment:*": { "subcaseMS": 1.400 },
"webgpu:shader,validation,parse,semicolon:after_call:*": { "subcaseMS": 1.301 },
"webgpu:shader,validation,parse,semicolon:after_case:*": { "subcaseMS": 1.301 },
Expand All @@ -1924,6 +1927,7 @@
"webgpu:shader,validation,parse,semicolon:after_continuing:*": { "subcaseMS": 0.900 },
"webgpu:shader,validation,parse,semicolon:after_default_case:*": { "subcaseMS": 3.100 },
"webgpu:shader,validation,parse,semicolon:after_default_case_break:*": { "subcaseMS": 1.000 },
"webgpu:shader,validation,parse,semicolon:after_diagnostic:*": { "subcaseMS": 1.000 },
"webgpu:shader,validation,parse,semicolon:after_discard:*": { "subcaseMS": 4.400 },
"webgpu:shader,validation,parse,semicolon:after_enable:*": { "subcaseMS": 1.301 },
"webgpu:shader,validation,parse,semicolon:after_fn_const_assert:*": { "subcaseMS": 1.400 },
Expand All @@ -1942,6 +1946,7 @@
"webgpu:shader,validation,parse,semicolon:after_member:*": { "subcaseMS": 4.801 },
"webgpu:shader,validation,parse,semicolon:after_module_const_decl:*": { "subcaseMS": 1.400 },
"webgpu:shader,validation,parse,semicolon:after_module_var_decl:*": { "subcaseMS": 0.901 },
"webgpu:shader,validation,parse,semicolon:after_requires:*": { "subcaseMS": 1.000 },
"webgpu:shader,validation,parse,semicolon:after_return:*": { "subcaseMS": 1.201 },
"webgpu:shader,validation,parse,semicolon:after_struct_decl:*": { "subcaseMS": 1.000 },
"webgpu:shader,validation,parse,semicolon:after_switch:*": { "subcaseMS": 1.101 },
Expand Down
21 changes: 21 additions & 0 deletions src/webgpu/shader/validation/parse/diagnostic.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,24 @@ g.test('conflicting_attribute_different_location')
const code = `${kNestedLocations[t.params.loc](d1, d2)}`;
t.expectCompileResult(true, code);
});

g.test('after_other_directives')
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#diagnostics')
.desc(`Tests other global directives before a diagnostic directive.`)
.params(u =>
u.combine('directive', ['enable f16', 'requires readonly_and_readwrite_storage_textures'])
)
.beforeAllSubcases(t => {
if (t.params.directive.startsWith('enable')) {
t.selectDeviceOrSkipTestCase('shader-f16');
}
})
.fn(t => {
if (t.params.directive.startsWith('requires')) {
t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures');
}

let code = `${t.params.directive};`;
code += generateDiagnostic('directive', 'info', 'derivative_uniformity') + ';';
t.expectCompileResult(true, code);
});
18 changes: 16 additions & 2 deletions src/webgpu/shader/validation/parse/enable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,21 @@ const kCases = {
enable f16;`,
pass: false,
},
after_decl: {
decl_after: {
code: `enable f16;
alias i = i32;`,
pass: true,
},
requires_before: {
code: `requires readonly_and_readwrite_storage_textures;
enable f16;`,
pass: true,
},
diagnostic_before: {
code: `diagnostic(info, derivative_uniformity);
enable f16;`,
pass: true,
},
const_assert_before: {
code: `const_assert 1 == 1;
enable f16;`,
Expand Down Expand Up @@ -48,7 +58,7 @@ f16;`,
enable f16;`,
pass: true,
},
multipe_entries: {
multiple_entries: {
code: `enable f16, f16, f16;`,
pass: true,
},
Expand All @@ -65,6 +75,10 @@ g.test('enable')
})
.params(u => u.combine('case', keysOf(kCases)))
.fn(t => {
if (t.params.case === 'requires_before') {
t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures');
}

const c = kCases[t.params.case];
t.expectCompileResult(c.pass, c.code);
});
105 changes: 105 additions & 0 deletions src/webgpu/shader/validation/parse/requires.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
export const description = `Parser validation tests for requires`;

import { makeTestGroup } from '../../../../common/framework/test_group.js';
import { keysOf } from '../../../../common/util/data_tables.js';
import { kKnownWGSLLanguageFeatures } from '../../../capability_info.js';
import { ShaderValidationTest } from '../shader_validation_test.js';

export const g = makeTestGroup(ShaderValidationTest);

const kCases = {
valid: { code: `requires readonly_and_readwrite_storage_textures;`, pass: true },
decl_before: {
code: `alias i = i32;
requires readonly_and_readwrite_storage_textures;`,
pass: false,
},
decl_after: {
code: `requires readonly_and_readwrite_storage_textures;
alias i = i32;`,
pass: true,
},
enable_before: {
code: `enable f16;
requires readonly_and_readwrite_storage_textures;`,
pass: true,
},
diagnostic_before: {
code: `diagnostic(info, derivative_uniformity);
requires readonly_and_readwrite_storage_textures;`,
pass: true,
},
const_assert_before: {
code: `const_assert 1 == 1;
requires readonly_and_readwrite_storage_textures;`,
pass: false,
},
const_assert_after: {
code: `requires readonly_and_readwrite_storage_textures;
const_assert 1 == 1;`,
pass: true,
},
embedded_comment: {
code: `/* comment
*/requires readonly_and_readwrite_storage_textures;`,
pass: true,
},
parens: {
code: `requires(readonly_and_readwrite_storage_textures);`,
pass: false,
},
multi_line: {
code: `requires
readonly_and_readwrite_storage_textures;`,
pass: true,
},
multiple_requires_duplicate: {
code: `requires readonly_and_readwrite_storage_textures;
requires readonly_and_readwrite_storage_textures;`,
pass: true,
},
multiple_requires_different: {
code: `requires readonly_and_readwrite_storage_textures;
requires packed_4x8_integer_dot_product;`,
pass: true,
},
multiple_entries_duplicate: {
code: `requires readonly_and_readwrite_storage_textures, readonly_and_readwrite_storage_textures, readonly_and_readwrite_storage_textures;`,
pass: true,
},
multiple_entries_different: {
code: `requires readonly_and_readwrite_storage_textures, packed_4x8_integer_dot_product;`,
pass: true,
},
unknown: {
code: `requires unknown;`,
pass: false,
},
};

g.test('requires')
.desc(`Tests that requires are validated correctly.`)
.params(u => u.combine('case', keysOf(kCases)))
.beforeAllSubcases(t => {
if (t.params.case === 'enable_before') {
t.selectDeviceOrSkipTestCase('shader-f16');
}
})
.fn(t => {
t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures');
t.skipIfLanguageFeatureNotSupported('packed_4x8_integer_dot_product');

const c = kCases[t.params.case];
t.expectCompileResult(c.pass, c.code);
});

g.test('wgsl_matches_api')
.desc(`Tests that language features are accepted iff the API reports support for them.`)
.params(u => u.combine('feature', kKnownWGSLLanguageFeatures))
.fn(t => {
t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures');

const code = `requires ${t.params.feature};`;
t.expectCompileResult(t.hasLanguageFeature(t.params.feature), code);
});
15 changes: 15 additions & 0 deletions src/webgpu/shader/validation/parse/semicolon.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,21 @@ g.test('after_enable')
t.expectCompileResult(/* pass */ false, `enable f16`);
});

g.test('after_requires')
.desc(`Test that a semicolon must be placed after a requires directive.`)
.fn(t => {
t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures');
t.expectCompileResult(/* pass */ true, `requires readonly_and_readwrite_storage_textures;`);
t.expectCompileResult(/* pass */ false, `requires readonly_and_readwrite_storage_textures`);
});

g.test('after_diagnostic')
.desc(`Test that a semicolon must be placed after a requires directive.`)
.fn(t => {
t.expectCompileResult(/* pass */ true, `diagnostic(info, derivative_uniformity);`);
t.expectCompileResult(/* pass */ false, `diagnostic(info, derivative_uniformity)`);
});

g.test('after_struct_decl')
.desc(`Test that a semicolon can be placed after an struct declaration.`)
.fn(t => {
Expand Down

0 comments on commit 66ef471

Please sign in to comment.