diff --git a/src/webgpu/listing_meta.json b/src/webgpu/listing_meta.json index 3f6ce7cd6f24..016584be6d2d 100644 --- a/src/webgpu/listing_meta.json +++ b/src/webgpu/listing_meta.json @@ -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 }, @@ -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 }, @@ -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 }, @@ -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 }, diff --git a/src/webgpu/shader/validation/parse/diagnostic.spec.ts b/src/webgpu/shader/validation/parse/diagnostic.spec.ts index 154a4253ead6..757cf50cbba4 100644 --- a/src/webgpu/shader/validation/parse/diagnostic.spec.ts +++ b/src/webgpu/shader/validation/parse/diagnostic.spec.ts @@ -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); + }); diff --git a/src/webgpu/shader/validation/parse/enable.spec.ts b/src/webgpu/shader/validation/parse/enable.spec.ts index 230244c6b870..799053b54782 100644 --- a/src/webgpu/shader/validation/parse/enable.spec.ts +++ b/src/webgpu/shader/validation/parse/enable.spec.ts @@ -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;`, @@ -48,7 +58,7 @@ f16;`, enable f16;`, pass: true, }, - multipe_entries: { + multiple_entries: { code: `enable f16, f16, f16;`, pass: true, }, @@ -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); }); diff --git a/src/webgpu/shader/validation/parse/requires.spec.ts b/src/webgpu/shader/validation/parse/requires.spec.ts new file mode 100644 index 000000000000..74d76e6b2c6b --- /dev/null +++ b/src/webgpu/shader/validation/parse/requires.spec.ts @@ -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); + }); diff --git a/src/webgpu/shader/validation/parse/semicolon.spec.ts b/src/webgpu/shader/validation/parse/semicolon.spec.ts index 87cffcfafc5d..15a225e19fef 100644 --- a/src/webgpu/shader/validation/parse/semicolon.spec.ts +++ b/src/webgpu/shader/validation/parse/semicolon.spec.ts @@ -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 => {