tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 20c8e55587d0da630253751844125468aa23d7d1
parent e7ac05af823bc27101b31cd7c1792428f09fd6fb
Author: Erich Gubler <erichdongubler@gmail.com>
Date:   Wed, 10 Dec 2025 16:55:07 +0000

Bug 2004624 - test(webgpu): update CTS to f7d27f91423683338da291a4a8bdb10dabebb42d r=webgpu-reviewers,nical

Notable "regressions":

- The immediate data API proposal has been added to CTS. This shouldn't be failing, and will receive some follow-up (see [`gpuweb`#5480](https://github.com/gpuweb/gpuweb/issues/5480)), but actually implementing this feature is tracked in <https://bugzilla.mozilla.org/show_bug.cgi?id=2005059>.
- In similar fashion, the transient textures proposal has been added to CTS, and shouldn't be failing. Follow-up to implement it is being tracked in <https://bugzilla.mozilla.org/show_bug.cgi?id=2005061>.

Differential Revision: https://phabricator.services.mozilla.com/D275409

Diffstat:
Mdom/webgpu/tests/cts/checkout/package-lock.json | 14+++++++-------
Mdom/webgpu/tests/cts/checkout/package.json | 2+-
Adom/webgpu/tests/cts/checkout/src/unittests/uniformity_snippet.spec.ts | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdom/webgpu/tests/cts/checkout/src/webgpu/api/validation/createBindGroup.spec.ts | 22++++++++++++++++++++++
Mdom/webgpu/tests/cts/checkout/src/webgpu/api/validation/createTexture.spec.ts | 24++++++++++++++++++++++--
Mdom/webgpu/tests/cts/checkout/src/webgpu/api/validation/createView.spec.ts | 11+++++++++++
Mdom/webgpu/tests/cts/checkout/src/webgpu/api/validation/encoding/encoder_open_state.spec.ts | 21+++++++++++++++++++++
Mdom/webgpu/tests/cts/checkout/src/webgpu/api/validation/render_pass/render_pass_descriptor.spec.ts | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Mdom/webgpu/tests/cts/checkout/src/webgpu/capability_info.ts | 9+++++++++
Mdom/webgpu/tests/cts/checkout/src/webgpu/constants.ts | 8++++++++
Mdom/webgpu/tests/cts/checkout/src/webgpu/idl/constants/flags.spec.ts | 1+
Adom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/uniformity/snippet.ts | 186+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/uniformity/uniformity.spec.ts | 533++++++++++++++++++++++++++++++++++++-------------------------------------------
Mdom/webgpu/tests/cts/checkout/tools/gen_version | 2+-
Mdom/webgpu/tests/cts/moz.yaml | 4++--
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/api/operation/adapter/requestDevice/cts.https.html.ini | 13+++++++++++++
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/createBindGroup/cts.https.html.ini | 18++++++++++++++++--
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/createTexture/cts.https.html.ini | 146+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/encoding/cmds/copyTextureToTexture/cts.https.html.ini | 2++
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/encoding/encoder_open_state/cts.https.html.ini | 9+++++++++
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/image_copy/buffer_texture_copies/cts.https.html.ini | 3+++
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/image_copy/texture_related/cts.https.html.ini | 8++++++++
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture/cts.https.html.ini | 3+++
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/render_pass/render_pass_descriptor/cts.https.html.ini | 124+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/resource_usages/texture/in_render_misc/cts.https.html.ini | 15+++++++++++++++
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/state/device_lost/destroy/cts.https.html.ini | 23+++++++++++------------
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/texture/bgra8unorm_storage/cts.https.html.ini | 6++++++
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/constants/flags/cts.https.html.ini | 6++++++
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/constants/flags/dedicated.https.html.ini | 6++++++
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/constants/flags/shared.https.html.ini | 6++++++
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/javascript/cts.https.html.ini | 11+++++++++--
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/javascript/dedicated.https.html.ini | 11+++++++++--
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/javascript/shared.https.html.ini | 11+++++++++--
Mtesting/web-platform/mozilla/meta/webgpu/cts/webgpu/shader/validation/uniformity/uniformity/cts.https.html.ini | 644+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Mtesting/web-platform/mozilla/tests/webgpu/common/internal/version.js | 2+-
Mtesting/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pass/render_pass_descriptor/cts.https.html | 1+
Mtesting/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroup.spec.js | 28+++++++++++++++++++++++++---
Mtesting/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createTexture.spec.js | 26+++++++++++++++++++++++---
Mtesting/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createView.spec.js | 15+++++++++++++--
Mtesting/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/encoder_open_state.spec.js | 21+++++++++++++++++++++
Mtesting/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/render_pass_descriptor.spec.js | 84++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mtesting/web-platform/mozilla/tests/webgpu/webgpu/capability_info.js | 13+++++++++++--
Mtesting/web-platform/mozilla/tests/webgpu/webgpu/constants.js | 10+++++++++-
Mtesting/web-platform/mozilla/tests/webgpu/webgpu/idl/constants/flags.spec.js | 3++-
Atesting/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/uniformity/snippet.js | 187+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtesting/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/uniformity/uniformity.spec.js | 523++++++++++++++++++++++++++++++++++++-------------------------------------------
46 files changed, 2272 insertions(+), 694 deletions(-)

diff --git a/dom/webgpu/tests/cts/checkout/package-lock.json b/dom/webgpu/tests/cts/checkout/package-lock.json @@ -24,7 +24,7 @@ "@types/w3c-image-capture": "^1.0.10", "@typescript-eslint/eslint-plugin": "^6.9.1", "@typescript-eslint/parser": "^6.9.1", - "@webgpu/types": "^0.1.66", + "@webgpu/types": "^0.1.67", "ansi-colors": "4.1.3", "babel-plugin-add-header-comment": "^1.0.3", "babel-plugin-const-enum": "^1.2.0", @@ -1539,9 +1539,9 @@ "dev": true }, "node_modules/@webgpu/types": { - "version": "0.1.66", - "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.66.tgz", - "integrity": "sha512-YA2hLrwLpDsRueNDXIMqN9NTzD6bCDkuXbOSe0heS+f8YE8usA6Gbv1prj81pzVHrbaAma7zObnIC+I6/sXJgA==", + "version": "0.1.67", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.67.tgz", + "integrity": "sha512-uk53+2ECGUkWoDFez/hymwpRfdgdIn6y1ref70fEecGMe5607f4sozNFgBk0oxlr7j2CRGWBEc3IBYMmFdGGTQ==", "dev": true, "license": "BSD-3-Clause" }, @@ -10077,9 +10077,9 @@ "dev": true }, "@webgpu/types": { - "version": "0.1.66", - "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.66.tgz", - "integrity": "sha512-YA2hLrwLpDsRueNDXIMqN9NTzD6bCDkuXbOSe0heS+f8YE8usA6Gbv1prj81pzVHrbaAma7zObnIC+I6/sXJgA==", + "version": "0.1.67", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.67.tgz", + "integrity": "sha512-uk53+2ECGUkWoDFez/hymwpRfdgdIn6y1ref70fEecGMe5607f4sozNFgBk0oxlr7j2CRGWBEc3IBYMmFdGGTQ==", "dev": true }, "abbrev": { diff --git a/dom/webgpu/tests/cts/checkout/package.json b/dom/webgpu/tests/cts/checkout/package.json @@ -50,7 +50,7 @@ "@types/w3c-image-capture": "^1.0.10", "@typescript-eslint/eslint-plugin": "^6.9.1", "@typescript-eslint/parser": "^6.9.1", - "@webgpu/types": "^0.1.66", + "@webgpu/types": "^0.1.67", "ansi-colors": "4.1.3", "babel-plugin-add-header-comment": "^1.0.3", "babel-plugin-const-enum": "^1.2.0", diff --git a/dom/webgpu/tests/cts/checkout/src/unittests/uniformity_snippet.spec.ts b/dom/webgpu/tests/cts/checkout/src/unittests/uniformity_snippet.spec.ts @@ -0,0 +1,69 @@ +export const description = ` +Test for shader uniformity code snippet generation. +`; + +import { makeTestGroup } from '../common/framework/test_group.js'; +import { specToCode } from '../webgpu/shader/validation/uniformity/snippet.js'; + +import { UnitTest } from './unit_test.js'; + +class F extends UnitTest { + test(spec: string, expect: string): void { + const got = specToCode(spec); + this.expect( + expect === got, + ` +expected: ${expect} +got: ${got}` + ); + } +} + +export const g = makeTestGroup(F); + +g.test('strings').fn(t => { + t.test( + 'loop-end', + ` loop { + } +` + ), + t.test( + 'loop-cond-break-op', + ` loop { + if <cond> {break;} + <op> + } +` + ), + t.test( + 'for-unif-always-return-op', + ` for (;<uniform_cond>;) { + return; + <op> + } +` + ), + t.test( + 'loop-op-continuing-cond-break', + ` loop { + <op> + continuing { + break if <cond>; + } + } +` + ), + t.test( + // This is the case suggested in https://github.com/gpuweb/cts/pull/4477#issuecomment-3408419425 + 'loop-always-return-continuing-cond-break-end-op', + ` loop { + return; + continuing { + break if <cond>; + } + } + <op> +` + ); +}); diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/createBindGroup.spec.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/createBindGroup.spec.ts @@ -23,6 +23,7 @@ import { kTextureViewDimensions, sampledAndStorageBindingEntries, texBindingTypeInfo, + IsValidTransientAttachmentUsage, } from '../../capability_info.js'; import { GPUConst } from '../../constants.js'; import { kPossibleStorageTextureFormats, kRegularTextureFormats } from '../../format_info.js'; @@ -199,6 +200,13 @@ g.test('texture_binding_must_have_correct_usage') .combine('usage', kTextureUsages) .unless(({ entry, usage }) => { const info = texBindingTypeInfo(entry); + // TRANSIENT_ATTACHMENT is only valid when combined with RENDER_ATTACHMENT, so skip. + if ( + usage === GPUConst.TextureUsage.TRANSIENT_ATTACHMENT && + info.resource !== 'sampledTexMS' + ) { + return true; + } // Can't create the texture for this (usage=STORAGE_BINDING and sampleCount=4), so skip. return usage === GPUConst.TextureUsage.STORAGE_BINDING && info.resource === 'sampledTexMS'; }) @@ -781,6 +789,13 @@ g.test('storage_texture,usage') // a combined usage. .combine('usage0', kTextureUsages) .combine('usage1', kTextureUsages) + .unless(({ usage0, usage1 }) => { + const usage = usage0 | usage1; + return ( + (usage & GPUConst.TextureUsage.TRANSIENT_ATTACHMENT) !== 0 && + !IsValidTransientAttachmentUsage(usage) + ); + }) ) .fn(t => { const { usage0, usage1 } = t.params; @@ -1212,6 +1227,13 @@ g.test('external_texture,texture_view,usage') // a combined usage. .combine('usage0', kTextureUsages) .combine('usage1', kTextureUsages) + .unless(({ usage0, usage1 }) => { + const usage = usage0 | usage1; + return ( + (usage & GPUConst.TextureUsage.TRANSIENT_ATTACHMENT) !== 0 && + !IsValidTransientAttachmentUsage(usage) + ); + }) ) .fn(t => { const { usage0, usage1 } = t.params; diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/createTexture.spec.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/createTexture.spec.ts @@ -3,7 +3,11 @@ export const description = `createTexture validation tests.`; import { AllFeaturesMaxLimitsGPUTest } from '../.././gpu_test.js'; import { makeTestGroup } from '../../../common/framework/test_group.js'; import { assert, makeValueTestVariant } from '../../../common/util/util.js'; -import { kTextureDimensions, kTextureUsages } from '../../capability_info.js'; +import { + kTextureDimensions, + kTextureUsages, + IsValidTransientAttachmentUsage, +} from '../../capability_info.js'; import { GPUConst } from '../../constants.js'; import { kAllTextureFormats, @@ -343,7 +347,11 @@ g.test('sampleCount,valid_sampleCount_with_other_parameter_varies') dimension !== '2d')) || ((usage & GPUConst.TextureUsage.STORAGE_BINDING) !== 0 && !isTextureFormatPossiblyStorageReadable(format)) || - (mipLevelCount !== 1 && dimension === '1d') + (mipLevelCount !== 1 && dimension === '1d') || + ((usage & GPUConst.TextureUsage.TRANSIENT_ATTACHMENT) !== 0 && + usage !== + (GPUConst.TextureUsage.RENDER_ATTACHMENT | + GPUConst.TextureUsage.TRANSIENT_ATTACHMENT)) ); }) ) @@ -1008,6 +1016,13 @@ g.test('texture_usage') .filter(({ dimension, format }) => textureFormatAndDimensionPossiblyCompatible(dimension, format) ) + .unless(({ usage0, usage1 }) => { + const usage = usage0 | usage1; + return ( + (usage & GPUConst.TextureUsage.TRANSIENT_ATTACHMENT) !== 0 && + !IsValidTransientAttachmentUsage(usage) + ); + }) ) .fn(t => { const { dimension, format, usage0, usage1 } = t.params; @@ -1037,6 +1052,11 @@ g.test('texture_usage') if (isColorTextureFormat(format) && !isTextureFormatColorRenderable(t.device, format)) success = false; } + if (usage & GPUTextureUsage.TRANSIENT_ATTACHMENT) { + if (usage !== (GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TRANSIENT_ATTACHMENT)) { + success = false; + } + } t.expectValidationError(() => { t.createTextureTracked(descriptor); diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/createView.spec.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/createView.spec.ts @@ -357,6 +357,13 @@ g.test('texture_view_usage') }) .beginSubcases() .combine('textureViewUsage', [0, ...kTextureUsages]) + .unless(({ textureUsage, textureViewUsage }) => { + // TRANSIENT_ATTACHMENT is only valid when combined with RENDER_ATTACHMENT. + return ( + textureUsage === GPUConst.TextureUsage.TRANSIENT_ATTACHMENT || + textureViewUsage === GPUConst.TextureUsage.TRANSIENT_ATTACHMENT + ); + }) ) .fn(t => { const { format, textureUsage, textureViewUsage } = t.params; @@ -394,6 +401,10 @@ g.test('texture_view_usage_with_view_format') .combine('usage', kTextureUsages) .beginSubcases() .combine('viewFormat', kAllTextureFormats) + .unless(({ usage }) => { + // TRANSIENT_ATTACHMENT is only valid when combined with RENDER_ATTACHMENT. + return usage === GPUConst.TextureUsage.TRANSIENT_ATTACHMENT; + }) ) .fn(t => { const { textureFormat, viewFormat, usage } = t.params; diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/encoding/encoder_open_state.spec.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/encoding/encoder_open_state.spec.ts @@ -98,6 +98,7 @@ const kRenderPassEncoderCommandInfo: { setScissorRect: {}, setBlendConstant: {}, setStencilReference: {}, + setImmediates: {}, beginOcclusionQuery: {}, endOcclusionQuery: {}, executeBundles: {}, @@ -122,6 +123,7 @@ const kRenderBundleEncoderCommandInfo: { setBindGroup: {}, setIndexBuffer: {}, setVertexBuffer: {}, + setImmediates: {}, pushDebugGroup: {}, popDebugGroup: {}, insertDebugMarker: {}, @@ -141,6 +143,7 @@ const kComputePassEncoderCommandInfo: { setPipeline: {}, dispatchWorkgroups: {}, dispatchWorkgroupsIndirect: {}, + setImmediates: {}, pushDebugGroup: {}, popDebugGroup: {}, insertDebugMarker: {}, @@ -391,6 +394,12 @@ g.test('render_pass_commands') renderPass.setStencilReference(0); } break; + case 'setImmediates': + { + const data = new Uint32Array(1); + renderPass.setImmediates(0, data, 0, 1); + } + break; case 'beginOcclusionQuery': { renderPass.beginOcclusionQuery(0); @@ -502,6 +511,12 @@ g.test('render_bundle_commands') bundleEncoder.setVertexBuffer(1, buffer); } break; + case 'setImmediates': + { + const data = new Uint32Array(1); + bundleEncoder.setImmediates(0, data, 0, 1); + } + break; case 'pushDebugGroup': { bundleEncoder.pushDebugGroup('group'); @@ -584,6 +599,12 @@ g.test('compute_pass_commands') computePass.dispatchWorkgroupsIndirect(indirectBuffer, 0); } break; + case 'setImmediates': + { + const data = new Uint32Array(1); + computePass.setImmediates(0, data, 0, 1); + } + break; case 'pushDebugGroup': { computePass.pushDebugGroup('group'); diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/render_pass/render_pass_descriptor.spec.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/render_pass/render_pass_descriptor.spec.ts @@ -718,6 +718,48 @@ g.test('attachments,mip_level_count') } }); +g.test('color_attachments,loadOp_storeOp') + .desc( + ` + Test GPURenderPassColorAttachment Usage: + - if usage includes TRANSIENT_ATTACHMENT + - loadOp must be clear + - storeOp must be discard + ` + ) + .params(u => + u + .combine('format', kPossibleColorRenderableTextureFormats) + .beginSubcases() + .combine('transientTexture', [true, false]) + .combine('loadOp', ['clear', 'load'] as GPULoadOp[]) + .combine('storeOp', ['discard', 'store'] as GPUStoreOp[]) + ) + .fn(t => { + const { format, transientTexture, loadOp, storeOp } = t.params; + + t.skipIfTextureFormatNotSupported(format); + t.skipIfTextureFormatNotUsableAsRenderAttachment(format); + + const usage = transientTexture + ? GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TRANSIENT_ATTACHMENT + : GPUTextureUsage.RENDER_ATTACHMENT; + + const texture = t.createTestTexture({ usage }); + + const colorAttachment = t.getColorAttachment(texture); + colorAttachment.loadOp = loadOp; + colorAttachment.storeOp = storeOp; + + const passDescriptor: GPURenderPassDescriptor = { + colorAttachments: [colorAttachment], + }; + + const success = !transientTexture || (loadOp === 'clear' && storeOp === 'discard'); + + t.tryRenderPass(success, passDescriptor); + }); + g.test('color_attachments,non_multisampled') .desc( ` @@ -1039,22 +1081,28 @@ g.test('depth_stencil_attachment,loadOp_storeOp_match_depthReadOnly_stencilReadO .desc( ` Test GPURenderPassDepthStencilAttachment Usage: - - if the format has a depth aspect: - - if depthReadOnly is true - - depthLoadOp and depthStoreOp must not be provided - - else: - - depthLoadOp and depthStoreOp must be provided - - if the format has a stencil aspect: - - if stencilReadOnly is true - - stencilLoadOp and stencilStoreOp must not be provided - - else: - - stencilLoadOp and stencilStoreOp must be provided + - if the format has a depth aspect and depthReadOnly is false + - depthLoadOp and depthStoreOp must be provided + - else: + - depthLoadOp and depthStoreOp must not be provided + - if the format has a stencil aspect and stencilReadOnly is false + - stencilLoadOp and stencilStoreOp must be provided + - else: + - stencilLoadOp and stencilStoreOp must not be provided + - if usage includes TRANSIENT_ATTACHMENT + - if the format has a depth aspect: + - depthLoadOp must be clear + - depthStoreOp must be discard + - if the format has a stencil aspect: + - stencilLoadOp must be clear + - stencilStoreOp must be discard ` ) .params(u => u .combine('format', kDepthStencilFormats) .beginSubcases() // Note: It's easier to debug if you comment this line out as you can then run an individual case. + .combine('transientTexture', [true, false]) .combine('depthReadOnly', [undefined, true, false]) .combine('depthLoadOp', [undefined, 'clear', 'load'] as GPULoadOp[]) .combine('depthStoreOp', [undefined, 'discard', 'store'] as GPUStoreOp[]) @@ -1065,6 +1113,7 @@ g.test('depth_stencil_attachment,loadOp_storeOp_match_depthReadOnly_stencilReadO .fn(t => { const { format, + transientTexture, depthReadOnly, depthLoadOp, depthStoreOp, @@ -1075,10 +1124,13 @@ g.test('depth_stencil_attachment,loadOp_storeOp_match_depthReadOnly_stencilReadO t.skipIfTextureFormatNotSupported(format); + const usage = transientTexture + ? GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TRANSIENT_ATTACHMENT + : GPUTextureUsage.RENDER_ATTACHMENT; const depthAttachment = t.createTextureTracked({ format, size: { width: 1, height: 1, depthOrArrayLayers: 1 }, - usage: GPUTextureUsage.RENDER_ATTACHMENT, + usage, }); const depthAttachmentView = depthAttachment.createView(); @@ -1120,7 +1172,13 @@ g.test('depth_stencil_attachment,loadOp_storeOp_match_depthReadOnly_stencilReadO const goodStencilCombo = hasStencil && !stencilReadOnly ? hasBothStencilOps : hasNeitherStencilOps; - const shouldError = !goodAspectSettingsPresent || !goodDepthCombo || !goodStencilCombo; + const goodTransient = + !transientTexture || + ((!hasDepth || (depthLoadOp === 'clear' && depthStoreOp === 'discard')) && + (!hasStencil || (stencilLoadOp === 'clear' && stencilStoreOp === 'discard'))); + + const shouldError = + !goodAspectSettingsPresent || !goodDepthCombo || !goodStencilCombo || !goodTransient; t.expectValidationError(() => { encoder.finish(); diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/capability_info.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/capability_info.ts @@ -210,10 +210,18 @@ export const kTextureUsageInfo: { [GPUConst.TextureUsage.TEXTURE_BINDING]: {}, [GPUConst.TextureUsage.STORAGE_BINDING]: {}, [GPUConst.TextureUsage.RENDER_ATTACHMENT]: {}, + [GPUConst.TextureUsage.TRANSIENT_ATTACHMENT]: {}, }; /** List of all GPUTextureUsage values. */ export const kTextureUsages = numericKeysOf<GPUTextureUsageFlags>(kTextureUsageInfo); +/** Check if `usage` is TRANSIENT_ATTACHMENT | RENDER_ATTACHMENT. */ +export function IsValidTransientAttachmentUsage(usage: GPUTextureUsageFlags): boolean { + return ( + usage === (GPUConst.TextureUsage.TRANSIENT_ATTACHMENT | GPUConst.TextureUsage.RENDER_ATTACHMENT) + ); +} + // Texture View /** Per-GPUTextureViewDimension info. */ @@ -768,6 +776,7 @@ const [kLimitInfoKeys, kLimitInfoDefaults, kLimitInfoData] = 'maxComputeWorkgroupSizeY': [ , 256, 128, ], 'maxComputeWorkgroupSizeZ': [ , 64, 64, ], 'maxComputeWorkgroupsPerDimension': [ , 65535, 65535, ], + 'maxImmediateSize': [ , 64, 64, ], } as const]; // MAINTENANCE_TODO: Remove when the compat spec is merged. diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/constants.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/constants.ts @@ -17,6 +17,13 @@ const BufferUsage = { } as const; checkType<typeof GPUBufferUsage>(BufferUsage); +declare global { + // MAINTENANCE_TODO: Remove this once TRANSIENT_ATTACHMENT is added to @webgpu/types + interface GPUTextureUsage { + readonly TRANSIENT_ATTACHMENT: GPUFlagsConstant; + } +} + const TextureUsage = { COPY_SRC: 0x01, COPY_DST: 0x02, @@ -25,6 +32,7 @@ const TextureUsage = { STORAGE_BINDING: 0x08, STORAGE: 0x08, RENDER_ATTACHMENT: 0x10, + TRANSIENT_ATTACHMENT: 0x20, } as const; checkType<typeof GPUTextureUsage>(TextureUsage); diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/idl/constants/flags.spec.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/idl/constants/flags.spec.ts @@ -35,6 +35,7 @@ const kTextureUsageExp = { TEXTURE_BINDING: 0x04, STORAGE_BINDING: 0x08, RENDER_ATTACHMENT: 0x10, + TRANSIENT_ATTACHMENT: 0x20, }; g.test('TextureUsage,count').fn(t => { t.assertMemberCount(GPUTextureUsage, kTextureUsageExp); diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/uniformity/snippet.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/uniformity/snippet.ts @@ -0,0 +1,186 @@ +export const description = 'Utilities for generating code snippets for uniformity tests'; + +import { assert, unreachable } from '../../../../common/util/util.js'; + +export type Verdict = + // sensitive: fail uniformity analysis if and only if + // - the condition is non-uniform, and + // - the operation requires uniformity + | 'sensitive' + + // forbid: fail uniformity analysis if and only if + // - the operation requires uniformity + | 'forbid' + + // permit: always passes uniformity analysis + | 'permit'; + +export function compileShouldSucceed({ + requires_uniformity, + condition_is_uniform, + verdict, +}: { + requires_uniformity: boolean; + condition_is_uniform: boolean; + verdict: Verdict; +}): boolean { + switch (verdict) { + case 'sensitive': + return !requires_uniformity || condition_is_uniform; + case 'forbid': + return !requires_uniformity; + case 'permit': + return true; + } +} + +export type Snippet = { + // A unique name for the case. + name: string; + // A WGSL code sippet that optionally embeds items to replaced later: + // - '<op>', an operation that does or does not require uniformity. + // - '<cond>', a condition which will be uniform or non-uniform + code: string; + // What is the verdict for this code snippet, after substitution of + // the operation and condition. + verdict: Verdict; +}; + +// We use a small domain-specific language that converts a +// string into a code snippet. +// +// NOTE: If you're confused about this scheme, see the unit tests +// in src/unittests/uniformity_snippet.spec.ts. Run them +// with `npm run unittest`. +// +// We process the name from left to right +// using the following component naming scheme: +// <kind-of-loop>, always appears first +// 'loop' +// 'for', for-loop with without a condition +// 'for-unif', for-loop with a uniform loop condition +// 'for-nonunif', for-loop with a non-uniform loop condition +// 'while-unif', while-loop with uniform loop condition +// 'while-nonunif', while-loop with non-uniform loop condition +// The next components are listed in order they appear in the code. +// <interrupt> : +// always-break, cond-break, +// always-return, cond-return, +// always-continue, cond-continue, +// The 'cond' variations will use a condition, either uniform +// or non-uniform, to be substituted later. +// 'unif-break': a loop break with uniform loop condition, used +// to avoid rejection due to infinite loop checks. +// 'op': +// 'continuing': indicates start of continuing block +// 'end': indicates end of the loop + +type LoopKind = 'loop' | 'for' | 'for-unif' | 'for-nonunif' | 'while-unif' | 'while-nonunif'; + +// Expand a loop case spec to its shader code +export function specToCode(spec: string): string { + let matches = spec.match('^(loop|for-unif|for-nonunif|for|while-unif|while-nonunif)-(.*)'); + assert(matches !== null, `invalid spec string: ${spec}`); + + let prefix = ' '; + const parts = []; + const end_parts = [prefix, '}\n']; // closing brace + + const kind = matches[1] as LoopKind; + let rest = matches[2]; + parts.push(prefix); + switch (kind) { + case 'loop': + parts.push('loop {'); + break; + case 'for': + parts.push('for (;;) {'); + break; + case 'for-unif': + parts.push(`for (;<uniform_cond>;) {`); + break; + case 'for-nonunif': + parts.push(`for (;<nonuniform_cond>;) {`); + break; + case 'while-unif': + parts.push(`while (<uniform_cond>) {`); + break; + case 'while-nonunif': + parts.push(`while (<nonuniform_cond>) {`); + break; + } + parts.push('\n'); + + let in_continuing = false; + prefix = ' '; + while (rest.length > 0) { + const current_len = rest.length; + matches = rest.match( + '^(op|continuing|end|unif-break|always-break|cond-break|unif-break|always-return|cond-return|always-continue|cond-continue)(-|$)(.*)' + ); + assert(matches !== null, `invalid spec string: ${spec}`); + const elem = matches[1]; + rest = matches[3]; + assert(rest.length < current_len, `pattern is not shrinking: '${rest}', from ${spec}`); + switch (elem) { + case 'op': + parts.push(prefix, '<op>\n'); // to be replaced later. + break; + case 'end': // end the loop + if (in_continuing) { + prefix = ' '; + } + prefix = ' '; + parts.push(...end_parts); + end_parts.length = 0; + in_continuing = false; + break; + case 'continuing': + parts.push(prefix, 'continuing {\n'); + end_parts.unshift(prefix, '}\n'); + in_continuing = true; + prefix = ' '; + break; + case 'unif-break': + assert(!in_continuing); + parts.push(prefix, `if <uniform_cond> {break;}\n`); + break; + case 'always-break': + assert(!in_continuing); + parts.push(prefix, 'break;\n'); + break; + case 'cond-break': + if (in_continuing) { + parts.push(prefix, `break if <cond>;\n`); + } else { + parts.push(prefix, `if <cond> {break;}\n`); + } + break; + case 'always-return': + assert(!in_continuing); + parts.push(prefix, 'return;\n'); + break; + case 'cond-return': + assert(!in_continuing); + parts.push(prefix, `if <cond> {return;}\n`); + break; + case 'always-continue': + assert(!in_continuing); + parts.push(prefix, 'continue;\n'); + break; + case 'cond-continue': + assert(!in_continuing); + parts.push(prefix, `if <cond> {continue;}\n`); + break; + default: + unreachable(`invalid loop case spec ${spec}`); + } + } + parts.push(...end_parts); + return parts.join(''); +} + +// Creates a Snippet from a loop spec string and a verdict. +export function LoopCase(spec: string, verdict: Verdict): Snippet { + return { name: spec, verdict, code: specToCode(spec) }; +} diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/uniformity/uniformity.spec.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/uniformity/uniformity.spec.ts @@ -5,6 +5,8 @@ import { keysOf } from '../../../../common/util/data_tables.js'; import { unreachable } from '../../../../common/util/util.js'; import { ShaderValidationTest } from '../shader_validation_test.js'; +import { Snippet, LoopCase, compileShouldSucceed } from './snippet.js'; + export const g = makeTestGroup(ShaderValidationTest); const kCollectiveOps = [ @@ -185,303 +187,240 @@ function generateOp(op: string): string { } } -const kStatementKinds = [ - 'if', - 'for', - 'while', - 'switch', - 'break-if', - 'loop-always-break-op-inside', - 'loop-always-return-op-inside', - 'loop-always-break-op-continuing', - 'loop-always-return-op-continuing', - 'loop-always-break-op-after', - 'loop-always-return-op-after', - 'for-with-cond-always-break-op-inside', - 'for-with-cond-always-return-op-inside', - 'for-with-cond-always-break-op-after', - 'for-with-cond-always-return-op-after', - 'for-without-cond-always-break-op-inside', - 'for-without-cond-always-return-op-inside', - 'for-without-cond-always-break-op-after', - 'for-without-cond-always-return-op-after', - 'while-always-break-op-inside', - 'while-always-return-op-inside', - 'while-always-break-op-after', - 'while-always-return-op-after', -] as const; -type kStatementType = (typeof kStatementKinds)[number]; +const kStatementCases = [ + // Basic non-loop cases. + { + name: 'if', + code: 'if <cond> { <op> }', + verdict: 'sensitive', + }, + { + name: 'switch', + code: ` + switch u32(<cond>) { + case 0: { + <op> + } + default: { } + }`, + verdict: 'sensitive', + }, + + // Loops + + // loop without continuing + // op before the interruption + LoopCase('loop-op-always-break', 'permit'), + LoopCase('loop-op-cond-break', 'sensitive'), + LoopCase('loop-op-always-return', 'permit'), + LoopCase('loop-op-cond-return', 'sensitive'), + LoopCase('loop-unif-break-op-always-continue', 'permit'), + LoopCase('loop-unif-break-op-cond-continue', 'sensitive'), + + // op after the interruption + LoopCase('loop-always-break-op', 'permit'), + LoopCase('loop-cond-break-op', 'sensitive'), + LoopCase('loop-always-return-op', 'permit'), + LoopCase('loop-cond-return-op', 'sensitive'), + LoopCase('loop-unif-break-always-continue-op', 'permit'), + LoopCase('loop-unif-break-cond-continue-op', 'sensitive'), + + // op after the end of the loop + // Without a return, any non-uniformity introduced in the + // loop is resolved by the end of the loop. + LoopCase('loop-always-break-end-op', 'permit'), + LoopCase('loop-unif-break-end-op', 'permit'), + LoopCase('loop-cond-break-end-op', 'permit'), + LoopCase('loop-always-return-end-op', 'permit'), + LoopCase('loop-cond-return-end-op', 'permit'), // the loop can only return + LoopCase('loop-unif-break-always-continue-end-op', 'permit'), + LoopCase('loop-unif-break-cond-continue-end-op', 'permit'), + + // loop with continuing block + // op before the interruption before continuing + LoopCase('loop-op-always-break-continuing', 'permit'), + LoopCase('loop-op-unif-break-continuing', 'permit'), + LoopCase('loop-op-cond-break-continuing', 'sensitive'), + LoopCase('loop-op-always-return-continuing', 'permit'), + LoopCase('loop-op-cond-return-continuing', 'sensitive'), + LoopCase('loop-unif-break-op-always-continue-continuing', 'permit'), + // non re-convergence at the continuing block. + LoopCase('loop-unif-break-op-cond-continue-continuing', 'sensitive'), + + // op in body, interruption in continiuing + // The only permitted interruption in the continuing block + // is cond-break. + LoopCase('loop-op-continuing-cond-break', 'sensitive'), + + // interruption in body, op in continuing + LoopCase('loop-always-break-continuing-op', 'permit'), + LoopCase('loop-cond-break-continuing-op', 'sensitive'), + LoopCase('loop-always-return-continuing-op', 'permit'), + LoopCase('loop-cond-return-continuing-op', 'sensitive'), + + // op and interruption in continuing + LoopCase('loop-continuing-op-cond-break', 'sensitive'), + + // interruption in body, op after end + LoopCase('loop-always-break-continuing-end-op', 'permit'), + LoopCase('loop-cond-break-continuing-end-op', 'permit'), + LoopCase('loop-always-return-continuing-end-op', 'permit'), + LoopCase('loop-cond-return-continuing-end-op', 'permit'), // the looop can only return + LoopCase('loop-unif-break-always-continue-continuing-end-op', 'permit'), + LoopCase('loop-unif-break-cond-continue-continuing-end-op', 'permit'), + + // interruption in continuing, op after end + LoopCase('loop-continuing-cond-break-end-op', 'permit'), + LoopCase('loop-always-break-continuing-cond-break-end-op', 'permit'), + LoopCase('loop-always-return-continuing-cond-break-end-op', 'permit'), + + // Unconditional for + // interruption then op + LoopCase('for-always-break-op', 'permit'), + LoopCase('for-cond-break-op', 'sensitive'), + LoopCase('for-always-return-op', 'permit'), + LoopCase('for-cond-return-op', 'sensitive'), + LoopCase('for-unif-unif-break-always-continue-op', 'permit'), + LoopCase('for-unif-unif-break-cond-continue-op', 'sensitive'), + // op then interruption + LoopCase('for-op-always-break', 'permit'), + LoopCase('for-op-cond-break', 'sensitive'), + LoopCase('for-op-always-return', 'permit'), + LoopCase('for-op-cond-return', 'sensitive'), + LoopCase('for-op-unif-break-always-continue', 'permit'), + LoopCase('for-op-unif-break-cond-continue', 'sensitive'), + + // For with uniform condition + LoopCase('for-unif-op', 'permit'), + // interruption, then op + LoopCase('for-unif-always-break-op', 'permit'), + LoopCase('for-unif-cond-break-op', 'sensitive'), + LoopCase('for-unif-always-return-op', 'permit'), + LoopCase('for-unif-cond-return-op', 'sensitive'), + LoopCase('for-unif-always-continue-op', 'permit'), + LoopCase('for-unif-cond-continue-op', 'sensitive'), + // op, then interruption + LoopCase('for-unif-op-always-break', 'permit'), + LoopCase('for-unif-op-cond-break', 'sensitive'), + LoopCase('for-unif-op-always-return', 'permit'), + LoopCase('for-unif-op-cond-return', 'sensitive'), + LoopCase('for-unif-op-always-continue', 'permit'), + LoopCase('for-unif-op-cond-continue', 'sensitive'), + // interruption, then op after loop + LoopCase('for-unif-end-op', 'permit'), + LoopCase('for-unif-always-break-end-op', 'permit'), + LoopCase('for-unif-cond-break-end-op', 'permit'), + LoopCase('for-unif-always-return-end-op', 'permit'), + LoopCase('for-unif-cond-return-end-op', 'sensitive'), + LoopCase('for-unif-always-continue-end-op', 'permit'), + LoopCase('for-unif-cond-continue-end-op', 'permit'), + + // For with non-uniform condition + LoopCase('for-nonunif-op', 'forbid'), + // interruption, then op + LoopCase('for-nonunif-always-break-op', 'permit'), + LoopCase('for-nonunif-cond-break-op', 'forbid'), + LoopCase('for-nonunif-always-return-op', 'permit'), + LoopCase('for-nonunif-cond-return-op', 'forbid'), + LoopCase('for-nonunif-always-continue-op', 'permit'), + LoopCase('for-nonunif-cond-continue-op', 'forbid'), + // op, then interruption + LoopCase('for-nonunif-op-always-break', 'forbid'), + LoopCase('for-nonunif-op-cond-break', 'forbid'), + LoopCase('for-nonunif-op-always-return', 'forbid'), + LoopCase('for-nonunif-op-cond-return', 'forbid'), + LoopCase('for-nonunif-op-always-continue', 'forbid'), + LoopCase('for-nonunif-op-cond-continue', 'forbid'), + // interruption, then op after loop + LoopCase('for-nonunif-end-op', 'permit'), + LoopCase('for-nonunif-always-break-end-op', 'permit'), + LoopCase('for-nonunif-cond-break-end-op', 'permit'), + LoopCase('for-nonunif-always-return-end-op', 'forbid'), + LoopCase('for-nonunif-cond-return-end-op', 'forbid'), + LoopCase('for-nonunif-always-continue-end-op', 'permit'), + LoopCase('for-nonunif-cond-continue-end-op', 'permit'), + + // While with uniform condition + LoopCase('while-unif-op', 'permit'), + // interruption, then op + LoopCase('while-unif-always-break-op', 'permit'), + LoopCase('while-unif-cond-break-op', 'sensitive'), + LoopCase('while-unif-always-return-op', 'permit'), + LoopCase('while-unif-cond-return-op', 'sensitive'), + LoopCase('while-unif-always-continue-op', 'permit'), + LoopCase('while-unif-cond-continue-op', 'sensitive'), + // op, then interruption + LoopCase('while-unif-op-always-break', 'permit'), + LoopCase('while-unif-op-cond-break', 'sensitive'), + LoopCase('while-unif-op-always-return', 'permit'), + LoopCase('while-unif-op-cond-return', 'sensitive'), + LoopCase('while-unif-op-always-continue', 'permit'), + LoopCase('while-unif-op-cond-continue', 'sensitive'), + // interruption, then op after loop + LoopCase('while-unif-end-op', 'permit'), + LoopCase('while-unif-always-break-end-op', 'permit'), + LoopCase('while-unif-cond-break-end-op', 'permit'), + LoopCase('while-unif-always-return-end-op', 'permit'), + LoopCase('while-unif-cond-return-end-op', 'sensitive'), + LoopCase('while-unif-always-continue-end-op', 'permit'), + LoopCase('while-unif-cond-continue-end-op', 'permit'), + + // While with non-uniform condition + LoopCase('while-nonunif-op', 'forbid'), + // interruption, then op + LoopCase('while-nonunif-always-break-op', 'permit'), + LoopCase('while-nonunif-cond-break-op', 'forbid'), + LoopCase('while-nonunif-always-return-op', 'permit'), + LoopCase('while-nonunif-cond-return-op', 'forbid'), + LoopCase('while-nonunif-always-continue-op', 'permit'), + LoopCase('while-nonunif-cond-continue-op', 'forbid'), + // op, then interruption + LoopCase('while-nonunif-op-always-break', 'forbid'), + LoopCase('while-nonunif-op-cond-break', 'forbid'), + LoopCase('while-nonunif-op-always-return', 'forbid'), + LoopCase('while-nonunif-op-cond-return', 'forbid'), + LoopCase('while-nonunif-op-always-continue', 'forbid'), + LoopCase('while-nonunif-op-cond-continue', 'forbid'), + // interruption, then op after loop + LoopCase('while-nonunif-end-op', 'permit'), + LoopCase('while-nonunif-always-break-end-op', 'permit'), + LoopCase('while-nonunif-cond-break-end-op', 'permit'), + LoopCase('while-nonunif-always-return-end-op', 'forbid'), + LoopCase('while-nonunif-cond-return-end-op', 'forbid'), + LoopCase('while-nonunif-always-continue-end-op', 'permit'), + LoopCase('while-nonunif-cond-continue-end-op', 'permit'), +]; + +const kStatementNames = kStatementCases.map(sc => sc.name); +type StatementName = (typeof kStatementNames)[number]; +// Lookup table by statement name +const kStatementDict = Object.fromEntries(kStatementCases.map(sc => [sc.name, sc])) as Record< + StatementName, + Snippet +>; -type kSnippetInfo = { - // A WGSL code sippet that embeds a condition and operation-operation-under-test - // in a larger construct. - code: string; - // Is the operation-under-test sensitive to the uniformity of the condition? - sensitive: boolean; -}; function generateConditionalStatement( - statement: kStatementType, + name: StatementName, condition_name: string, op_name: string -): kSnippetInfo { +): Snippet { const cond = generateCondition(condition_name); - const uniform_cond = generateCondition('uniform_storage_ro'); const op = generateOp(op_name); - switch (statement) { - case 'if': { - return { - sensitive: true, - code: ` - if ${cond} { - ${op}; - }`, - }; - } - case 'for': { - return { - sensitive: true, - code: ` - for (; ${cond}; ) { - ${op}; - }`, - }; - } - case 'while': { - return { - sensitive: true, - code: ` - while ${cond} { - ${op}; - }`, - }; - } - case 'switch': { - return { - sensitive: true, - code: ` - switch u32(${cond}) { - case 0: { - ${op}; - } - default: { } - }`, - }; - } - case 'break-if': { - // The initial 'if' prevents the loop from being infinite. Its condition - // is uniform, to ensure the first iteration of the the body executes - // uniformly. The uniformity of the second iteration depends entirely on - // the uniformity of the break-if condition. - return { - sensitive: true, - code: ` - loop { - if ${uniform_cond} { break; } - ${op} - continuing { - break if ${cond}; - } - }`, - }; - } - case 'loop-always-break-op-inside': { - return { - sensitive: false, // The op is unreachable. - code: ` - loop { - break; - if ${cond} { ${op} } - }`, - }; - } - case 'loop-always-return-op-inside': { - return { - sensitive: false, // The op is unreachable. - code: ` - loop { - return; - if ${cond} { ${op} } - }`, - }; - } - case 'loop-always-break-op-continuing': { - return { - sensitive: false, // The op is unreachable. - code: ` - loop { - break; - continuing { - if ${cond} { ${op} } - } - }`, - }; - } - case 'loop-always-return-op-continuing': { - return { - sensitive: false, // The op is unreachable. - code: ` - loop { - return; - continuing { - if ${cond} { ${op} } - } - }`, - }; - } - case 'loop-always-break-op-after': { - return { - sensitive: true, - code: ` - loop { - break; - } - if ${cond} { ${op} }`, - }; - } - case 'loop-always-return-op-after': { - return { - sensitive: false, // The op is unreachable. - code: ` - loop { - return; - } - if ${cond} { ${op} }`, - }; - } - case 'for-with-cond-always-break-op-inside': { - return { - sensitive: false, // The op is unreachable. - code: ` - for ( ;${uniform_cond}; ) { - break; - if ${cond} { ${op} } - }`, - }; - } - case 'for-with-cond-always-return-op-inside': { - return { - sensitive: false, // The op is unreachable. - code: ` - for ( ;${uniform_cond}; ) { - return; - if ${cond} { ${op} } - }`, - }; - } - case 'for-with-cond-always-break-op-after': { - return { - sensitive: true, - code: ` - for ( ;${uniform_cond}; ) { - break; - } - if ${cond} { ${op} }`, - }; - } - case 'for-with-cond-always-return-op-after': { - return { - // Desugars to a loop with a conditional break, - // before reaching the loop. - sensitive: true, - code: ` - for ( ;${uniform_cond}; ) { - return; - } - if ${cond} { ${op} }`, - }; - } - case 'for-without-cond-always-break-op-inside': { - return { - sensitive: false, // The op is unreachable. - code: ` - for ( ; ; ) { - break; - if ${cond} { ${op} } - }`, - }; - } - case 'for-without-cond-always-return-op-inside': { - return { - sensitive: false, // The op is unreachable. - code: ` - for ( ; ; ) { - return; - if ${cond} { ${op} } - }`, - }; - } - case 'for-without-cond-always-break-op-after': { - return { - sensitive: true, - code: ` - for ( ; ; ) { - break; - } - if ${cond} { ${op} }`, - }; - } - case 'for-without-cond-always-return-op-after': { - return { - // Desugars to a loop without a conditional break. - // So the op is unreachable. - sensitive: false, - code: ` - for ( ; ; ) { - return; - } - if ${cond} { ${op} }`, - }; - } - case 'while-always-break-op-inside': { - return { - sensitive: false, // The op is unreachable. - code: ` - while (${uniform_cond}) { - break; - if ${cond} { ${op} } - }`, - }; - } - case 'while-always-return-op-inside': { - return { - sensitive: false, // The op is unreachable. - code: ` - while (${uniform_cond}) { - return; - if ${cond} { ${op} } - }`, - }; - } - case 'while-always-break-op-after': { - return { - sensitive: true, - code: ` - while (${uniform_cond}) { - break; - } - if ${cond} { ${op} }`, - }; - } - case 'while-always-return-op-after': { - return { - // Desugars to a loop with a conditional break, - // before reaching the loop. - sensitive: true, - code: ` - while (${uniform_cond}) { - return; - } - if ${cond} { ${op} }`, - }; - } - } + const snippet = kStatementDict[name]; + let code = snippet.code; + code = code + .replace('<op>', op) + .replace('<cond>', cond) + .replaceAll('<uniform_cond>', generateCondition('uniform_storage_ro')) + .replaceAll('<nonuniform_cond>', generateCondition('nonuniform_storage_ro')); + return { name, code, verdict: snippet.verdict }; } g.test('basics') .desc(`Test collective operations in simple uniform or non-uniform control flow.`) .params(u => u - .combine('statement', kStatementKinds) + .combine('statement', kStatementNames) .beginSubcases() .combineWithParams(kConditions) .combineWithParams(kCollectiveOps) @@ -522,11 +461,11 @@ g.test('basics') code += `@builtin(position) p : vec4<f32>`; } code += `) { - let u_let = uniform_buffer.x; - let n_let = rw_buffer[0]; - var u_f = uniform_buffer.z; - var n_f = rw_buffer[1]; - `; + let u_let = uniform_buffer.x; + let n_let = rw_buffer[0]; + var u_f = uniform_buffer.z; + var n_f = rw_buffer[1]; +`; // Simple control statement containing the op. const snippet = generateConditionalStatement(t.params.statement, t.params.cond, t.params.op); @@ -535,7 +474,11 @@ g.test('basics') code += `\n}\n`; t.expectCompileResult( - t.params.expectation || t.params.op.startsWith('control_case') || !snippet.sensitive, + compileShouldSucceed({ + requires_uniformity: !t.params.op.startsWith('control_case'), + condition_is_uniform: t.params.expectation, + verdict: snippet.verdict, + }), code ); }); @@ -573,7 +516,7 @@ g.test('basics,subgroups') .desc(`Test subgroup operations in simple uniform or non-uniform control flow.`) .params(u => u - .combine('statement', kStatementKinds) + .combine('statement', kStatementNames) .beginSubcases() .combineWithParams(kConditions) .combine('op', kSubgroupOps) @@ -626,7 +569,11 @@ g.test('basics,subgroups') code += `\n}\n`; t.expectCompileResult( - t.params.expectation || t.params.op.startsWith('control_case') || !snippet.sensitive, + compileShouldSucceed({ + requires_uniformity: !t.params.op.startsWith('control_case'), + condition_is_uniform: t.params.expectation, + verdict: snippet.verdict, + }), code ); }); diff --git a/dom/webgpu/tests/cts/checkout/tools/gen_version b/dom/webgpu/tests/cts/checkout/tools/gen_version @@ -14,7 +14,7 @@ if (!fs.existsSync(myself)) { process.exit(1); } -const version = 'ef27c0b88b802ca64677e2c0ed60378951ac6c42'; +const version = 'f7d27f91423683338da291a4a8bdb10dabebb42d'; fs.mkdirSync('./gen/common/internal', { recursive: true }); // This will be copied into the various other build directories. diff --git a/dom/webgpu/tests/cts/moz.yaml b/dom/webgpu/tests/cts/moz.yaml @@ -8,8 +8,8 @@ origin: name: WebGPU CTS description: WebGPU Compliance Test Suite url: https://gpuweb.github.io/cts/ - release: ef27c0b88b802ca64677e2c0ed60378951ac6c42 (2025-11-28T22:30:43Z). - revision: ef27c0b88b802ca64677e2c0ed60378951ac6c42 + release: f7d27f91423683338da291a4a8bdb10dabebb42d (2025-12-05T21:09:46Z). + revision: f7d27f91423683338da291a4a8bdb10dabebb42d license: ['BSD-3-Clause'] updatebot: diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/operation/adapter/requestDevice/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/operation/adapter/requestDevice/cts.https.html.ini @@ -67,6 +67,7 @@ [cts.https.html?q=webgpu:api,operation,adapter,requestDevice:limit,better_than_supported:*] + implementation-status: backlog [:limit="maxBindGroups"] [:limit="maxBindGroupsPlusVertexBuffers"] @@ -95,6 +96,9 @@ [:limit="maxDynamicUniformBuffersPerPipelineLayout"] + [:limit="maxImmediateSize"] + expected: FAIL + [:limit="maxInterStageShaderVariables"] [:limit="maxSampledTexturesPerShaderStage"] @@ -169,6 +173,9 @@ [:limit="maxDynamicUniformBuffersPerPipelineLayout"] + [:limit="maxImmediateSize"] + expected: FAIL + [:limit="maxInterStageShaderVariables"] [:limit="maxSampledTexturesPerShaderStage"] @@ -246,6 +253,9 @@ [:limit="maxDynamicUniformBuffersPerPipelineLayout"] + [:limit="maxImmediateSize"] + expected: FAIL + [:limit="maxInterStageShaderVariables"] [:limit="maxSampledTexturesPerShaderStage"] @@ -334,6 +344,9 @@ [:limit="maxDynamicUniformBuffersPerPipelineLayout"] expected: FAIL + [:limit="maxImmediateSize"] + expected: FAIL + [:limit="maxInterStageShaderVariables"] expected: FAIL diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/createBindGroup/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/createBindGroup/cts.https.html.ini @@ -581,8 +581,7 @@ [cts.https.html?q=webgpu:api,validation,createBindGroup:external_texture,texture_view,usage:*] - implementation-status: - if os == "linux": backlog + implementation-status: backlog [:usage0=16;usage1=1] expected: if os == "linux": FAIL @@ -595,6 +594,9 @@ expected: if os == "linux": FAIL + [:usage0=16;usage1=32] + expected: FAIL + [:usage0=16;usage1=4] expected: if os == "linux": FAIL @@ -643,6 +645,9 @@ expected: if os == "linux": FAIL + [:usage0=32;usage1=16] + expected: FAIL + [:usage0=4;usage1=1] expected: if os == "linux": FAIL @@ -4236,12 +4241,16 @@ [cts.https.html?q=webgpu:api,validation,createBindGroup:storage_texture,usage:*] + implementation-status: backlog [:usage0=16;usage1=1] [:usage0=16;usage1=16] [:usage0=16;usage1=2] + [:usage0=16;usage1=32] + expected: FAIL + [:usage0=16;usage1=4] [:usage0=16;usage1=8] @@ -4266,6 +4275,9 @@ [:usage0=2;usage1=8] + [:usage0=32;usage1=16] + expected: FAIL + [:usage0=4;usage1=1] [:usage0=4;usage1=16] @@ -4294,7 +4306,9 @@ [cts.https.html?q=webgpu:api,validation,createBindGroup:texture_binding_must_have_correct_usage:*] + implementation-status: backlog [:] + expected: FAIL [cts.https.html?q=webgpu:api,validation,createBindGroup:texture_must_have_correct_component_type:*] diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/createTexture/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/createTexture/cts.https.html.ini @@ -1481,6 +1481,7 @@ [cts.https.html?q=webgpu:api,validation,createTexture:sampleCount,valid_sampleCount_with_other_parameter_varies:*] + implementation-status: backlog [:dimension="1d";format="bgra8unorm"] [:dimension="1d";format="bgra8unorm-srgb"] @@ -1652,8 +1653,10 @@ [:dimension="2d";format="bc7-rgba-unorm-srgb"] [:dimension="2d";format="bgra8unorm"] + expected: FAIL [:dimension="2d";format="bgra8unorm-srgb"] + expected: FAIL [:dimension="2d";format="depth16unorm"] @@ -1686,86 +1689,117 @@ [:dimension="2d";format="etc2-rgba8unorm-srgb"] [:dimension="2d";format="r16float"] + expected: FAIL [:dimension="2d";format="r16sint"] + expected: FAIL [:dimension="2d";format="r16snorm"] [:dimension="2d";format="r16uint"] + expected: FAIL [:dimension="2d";format="r16unorm"] [:dimension="2d";format="r32float"] + expected: FAIL [:dimension="2d";format="r32sint"] + expected: FAIL [:dimension="2d";format="r32uint"] + expected: FAIL [:dimension="2d";format="r8sint"] + expected: FAIL [:dimension="2d";format="r8snorm"] [:dimension="2d";format="r8uint"] + expected: FAIL [:dimension="2d";format="r8unorm"] + expected: FAIL [:dimension="2d";format="rg11b10ufloat"] + expected: FAIL [:dimension="2d";format="rg16float"] + expected: FAIL [:dimension="2d";format="rg16sint"] + expected: FAIL [:dimension="2d";format="rg16snorm"] [:dimension="2d";format="rg16uint"] + expected: FAIL [:dimension="2d";format="rg16unorm"] [:dimension="2d";format="rg32float"] + expected: FAIL [:dimension="2d";format="rg32sint"] + expected: FAIL [:dimension="2d";format="rg32uint"] + expected: FAIL [:dimension="2d";format="rg8sint"] + expected: FAIL [:dimension="2d";format="rg8snorm"] [:dimension="2d";format="rg8uint"] + expected: FAIL [:dimension="2d";format="rg8unorm"] + expected: FAIL [:dimension="2d";format="rgb10a2uint"] + expected: FAIL [:dimension="2d";format="rgb10a2unorm"] + expected: FAIL [:dimension="2d";format="rgb9e5ufloat"] [:dimension="2d";format="rgba16float"] + expected: FAIL [:dimension="2d";format="rgba16sint"] + expected: FAIL [:dimension="2d";format="rgba16snorm"] [:dimension="2d";format="rgba16uint"] + expected: FAIL [:dimension="2d";format="rgba16unorm"] [:dimension="2d";format="rgba32float"] + expected: FAIL [:dimension="2d";format="rgba32sint"] + expected: FAIL [:dimension="2d";format="rgba32uint"] + expected: FAIL [:dimension="2d";format="rgba8sint"] + expected: FAIL [:dimension="2d";format="rgba8snorm"] [:dimension="2d";format="rgba8uint"] + expected: FAIL [:dimension="2d";format="rgba8unorm"] + expected: FAIL [:dimension="2d";format="rgba8unorm-srgb"] + expected: FAIL [:dimension="2d";format="stencil8"] @@ -5484,6 +5518,7 @@ [cts.https.html?q=webgpu:api,validation,createTexture:texture_usage:*] + implementation-status: backlog [:dimension="1d";format="bgra8unorm"] [:dimension="1d";format="bgra8unorm-srgb"] @@ -5655,18 +5690,25 @@ [:dimension="2d";format="bc7-rgba-unorm-srgb"] [:dimension="2d";format="bgra8unorm"] + expected: FAIL [:dimension="2d";format="bgra8unorm-srgb"] + expected: FAIL [:dimension="2d";format="depth16unorm"] + expected: FAIL [:dimension="2d";format="depth24plus"] + expected: FAIL [:dimension="2d";format="depth24plus-stencil8"] + expected: FAIL [:dimension="2d";format="depth32float"] + expected: FAIL [:dimension="2d";format="depth32float-stencil8"] + expected: FAIL [:dimension="2d";format="eac-r11snorm"] @@ -5689,88 +5731,120 @@ [:dimension="2d";format="etc2-rgba8unorm-srgb"] [:dimension="2d";format="r16float"] + expected: FAIL [:dimension="2d";format="r16sint"] + expected: FAIL [:dimension="2d";format="r16snorm"] [:dimension="2d";format="r16uint"] + expected: FAIL [:dimension="2d";format="r16unorm"] [:dimension="2d";format="r32float"] + expected: FAIL [:dimension="2d";format="r32sint"] + expected: FAIL [:dimension="2d";format="r32uint"] + expected: FAIL [:dimension="2d";format="r8sint"] + expected: FAIL [:dimension="2d";format="r8snorm"] [:dimension="2d";format="r8uint"] + expected: FAIL [:dimension="2d";format="r8unorm"] + expected: FAIL [:dimension="2d";format="rg11b10ufloat"] + expected: FAIL [:dimension="2d";format="rg16float"] + expected: FAIL [:dimension="2d";format="rg16sint"] + expected: FAIL [:dimension="2d";format="rg16snorm"] [:dimension="2d";format="rg16uint"] + expected: FAIL [:dimension="2d";format="rg16unorm"] [:dimension="2d";format="rg32float"] + expected: FAIL [:dimension="2d";format="rg32sint"] + expected: FAIL [:dimension="2d";format="rg32uint"] + expected: FAIL [:dimension="2d";format="rg8sint"] + expected: FAIL [:dimension="2d";format="rg8snorm"] [:dimension="2d";format="rg8uint"] + expected: FAIL [:dimension="2d";format="rg8unorm"] + expected: FAIL [:dimension="2d";format="rgb10a2uint"] + expected: FAIL [:dimension="2d";format="rgb10a2unorm"] + expected: FAIL [:dimension="2d";format="rgb9e5ufloat"] [:dimension="2d";format="rgba16float"] + expected: FAIL [:dimension="2d";format="rgba16sint"] + expected: FAIL [:dimension="2d";format="rgba16snorm"] [:dimension="2d";format="rgba16uint"] + expected: FAIL [:dimension="2d";format="rgba16unorm"] [:dimension="2d";format="rgba32float"] + expected: FAIL [:dimension="2d";format="rgba32sint"] + expected: FAIL [:dimension="2d";format="rgba32uint"] + expected: FAIL [:dimension="2d";format="rgba8sint"] + expected: FAIL [:dimension="2d";format="rgba8snorm"] [:dimension="2d";format="rgba8uint"] + expected: FAIL [:dimension="2d";format="rgba8unorm"] + expected: FAIL [:dimension="2d";format="rgba8unorm-srgb"] + expected: FAIL [:dimension="2d";format="stencil8"] + expected: FAIL [:dimension="3d";format="astc-10x10-unorm"] @@ -5857,90 +5931,123 @@ [:dimension="3d";format="bc7-rgba-unorm-srgb"] [:dimension="3d";format="bgra8unorm"] + expected: FAIL [:dimension="3d";format="bgra8unorm-srgb"] + expected: FAIL [:dimension="3d";format="r16float"] + expected: FAIL [:dimension="3d";format="r16sint"] + expected: FAIL [:dimension="3d";format="r16snorm"] [:dimension="3d";format="r16uint"] + expected: FAIL [:dimension="3d";format="r16unorm"] [:dimension="3d";format="r32float"] + expected: FAIL [:dimension="3d";format="r32sint"] + expected: FAIL [:dimension="3d";format="r32uint"] + expected: FAIL [:dimension="3d";format="r8sint"] + expected: FAIL [:dimension="3d";format="r8snorm"] [:dimension="3d";format="r8uint"] + expected: FAIL [:dimension="3d";format="r8unorm"] + expected: FAIL [:dimension="3d";format="rg11b10ufloat"] + expected: FAIL [:dimension="3d";format="rg16float"] + expected: FAIL [:dimension="3d";format="rg16sint"] + expected: FAIL [:dimension="3d";format="rg16snorm"] [:dimension="3d";format="rg16uint"] + expected: FAIL [:dimension="3d";format="rg16unorm"] [:dimension="3d";format="rg32float"] + expected: FAIL [:dimension="3d";format="rg32sint"] + expected: FAIL [:dimension="3d";format="rg32uint"] + expected: FAIL [:dimension="3d";format="rg8sint"] + expected: FAIL [:dimension="3d";format="rg8snorm"] [:dimension="3d";format="rg8uint"] + expected: FAIL [:dimension="3d";format="rg8unorm"] + expected: FAIL [:dimension="3d";format="rgb10a2uint"] + expected: FAIL [:dimension="3d";format="rgb10a2unorm"] + expected: FAIL [:dimension="3d";format="rgb9e5ufloat"] [:dimension="3d";format="rgba16float"] + expected: FAIL [:dimension="3d";format="rgba16sint"] + expected: FAIL [:dimension="3d";format="rgba16snorm"] [:dimension="3d";format="rgba16uint"] + expected: FAIL [:dimension="3d";format="rgba16unorm"] [:dimension="3d";format="rgba32float"] + expected: FAIL [:dimension="3d";format="rgba32sint"] + expected: FAIL [:dimension="3d";format="rgba32uint"] + expected: FAIL [:dimension="3d";format="rgba8sint"] + expected: FAIL [:dimension="3d";format="rgba8snorm"] [:dimension="3d";format="rgba8uint"] + expected: FAIL [:dimension="3d";format="rgba8unorm"] + expected: FAIL [:dimension="3d";format="rgba8unorm-srgb"] + expected: FAIL [:dimension="_undef_";format="astc-10x10-unorm"] @@ -6027,18 +6134,25 @@ [:dimension="_undef_";format="bc7-rgba-unorm-srgb"] [:dimension="_undef_";format="bgra8unorm"] + expected: FAIL [:dimension="_undef_";format="bgra8unorm-srgb"] + expected: FAIL [:dimension="_undef_";format="depth16unorm"] + expected: FAIL [:dimension="_undef_";format="depth24plus"] + expected: FAIL [:dimension="_undef_";format="depth24plus-stencil8"] + expected: FAIL [:dimension="_undef_";format="depth32float"] + expected: FAIL [:dimension="_undef_";format="depth32float-stencil8"] + expected: FAIL [:dimension="_undef_";format="eac-r11snorm"] @@ -6061,88 +6175,120 @@ [:dimension="_undef_";format="etc2-rgba8unorm-srgb"] [:dimension="_undef_";format="r16float"] + expected: FAIL [:dimension="_undef_";format="r16sint"] + expected: FAIL [:dimension="_undef_";format="r16snorm"] [:dimension="_undef_";format="r16uint"] + expected: FAIL [:dimension="_undef_";format="r16unorm"] [:dimension="_undef_";format="r32float"] + expected: FAIL [:dimension="_undef_";format="r32sint"] + expected: FAIL [:dimension="_undef_";format="r32uint"] + expected: FAIL [:dimension="_undef_";format="r8sint"] + expected: FAIL [:dimension="_undef_";format="r8snorm"] [:dimension="_undef_";format="r8uint"] + expected: FAIL [:dimension="_undef_";format="r8unorm"] + expected: FAIL [:dimension="_undef_";format="rg11b10ufloat"] + expected: FAIL [:dimension="_undef_";format="rg16float"] + expected: FAIL [:dimension="_undef_";format="rg16sint"] + expected: FAIL [:dimension="_undef_";format="rg16snorm"] [:dimension="_undef_";format="rg16uint"] + expected: FAIL [:dimension="_undef_";format="rg16unorm"] [:dimension="_undef_";format="rg32float"] + expected: FAIL [:dimension="_undef_";format="rg32sint"] + expected: FAIL [:dimension="_undef_";format="rg32uint"] + expected: FAIL [:dimension="_undef_";format="rg8sint"] + expected: FAIL [:dimension="_undef_";format="rg8snorm"] [:dimension="_undef_";format="rg8uint"] + expected: FAIL [:dimension="_undef_";format="rg8unorm"] + expected: FAIL [:dimension="_undef_";format="rgb10a2uint"] + expected: FAIL [:dimension="_undef_";format="rgb10a2unorm"] + expected: FAIL [:dimension="_undef_";format="rgb9e5ufloat"] [:dimension="_undef_";format="rgba16float"] + expected: FAIL [:dimension="_undef_";format="rgba16sint"] + expected: FAIL [:dimension="_undef_";format="rgba16snorm"] [:dimension="_undef_";format="rgba16uint"] + expected: FAIL [:dimension="_undef_";format="rgba16unorm"] [:dimension="_undef_";format="rgba32float"] + expected: FAIL [:dimension="_undef_";format="rgba32sint"] + expected: FAIL [:dimension="_undef_";format="rgba32uint"] + expected: FAIL [:dimension="_undef_";format="rgba8sint"] + expected: FAIL [:dimension="_undef_";format="rgba8snorm"] [:dimension="_undef_";format="rgba8uint"] + expected: FAIL [:dimension="_undef_";format="rgba8unorm"] + expected: FAIL [:dimension="_undef_";format="rgba8unorm-srgb"] + expected: FAIL [:dimension="_undef_";format="stencil8"] + expected: FAIL [cts.https.html?q=webgpu:api,validation,createTexture:viewFormats:*] diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/encoding/cmds/copyTextureToTexture/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/encoding/cmds/copyTextureToTexture/cts.https.html.ini @@ -10516,4 +10516,6 @@ [cts.https.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:texture_usage:*] + implementation-status: backlog [:] + expected: FAIL diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/encoding/encoder_open_state/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/encoding/encoder_open_state/cts.https.html.ini @@ -18,6 +18,9 @@ [:command="setBindGroup"] expected: FAIL + [:command="setImmediates"] + expected: FAIL + [:command="setPipeline"] expected: FAIL @@ -72,6 +75,9 @@ [:command="setBindGroup"] expected: FAIL + [:command="setImmediates"] + expected: FAIL + [:command="setIndexBuffer"] expected: FAIL @@ -124,6 +130,9 @@ [:command="setBlendConstant"] expected: FAIL + [:command="setImmediates"] + expected: FAIL + [:command="setIndexBuffer"] expected: FAIL diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/image_copy/buffer_texture_copies/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/image_copy/buffer_texture_copies/cts.https.html.ini @@ -979,6 +979,9 @@ [cts.https.html?q=webgpu:api,validation,image_copy,buffer_texture_copies:texture_buffer_usages:*] + implementation-status: backlog [:copyType="CopyB2T"] + expected: FAIL [:copyType="CopyT2B"] + expected: FAIL diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/image_copy/texture_related/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/image_copy/texture_related/cts.https.html.ini @@ -5259,20 +5259,28 @@ expected: FAIL [:method="CopyT2B";dimension="1d";size=[4,1,1\]] + expected: FAIL [:method="CopyT2B";dimension="2d";size=[4,4,1\]] + expected: FAIL [:method="CopyT2B";dimension="2d";size=[4,4,3\]] + expected: FAIL [:method="CopyT2B";dimension="3d";size=[4,4,3\]] + expected: FAIL [:method="WriteTexture";dimension="1d";size=[4,1,1\]] + expected: FAIL [:method="WriteTexture";dimension="2d";size=[4,4,1\]] + expected: FAIL [:method="WriteTexture";dimension="2d";size=[4,4,3\]] + expected: FAIL [:method="WriteTexture";dimension="3d";size=[4,4,3\]] + expected: FAIL [cts.https.html?q=webgpu:api,validation,image_copy,texture_related:valid:*] diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture/cts.https.html.ini @@ -320,6 +320,9 @@ [:usage=2] expected: FAIL + [:usage=32] + expected: FAIL + [:usage=4] expected: FAIL diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/render_pass/render_pass_descriptor/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/render_pass/render_pass_descriptor/cts.https.html.ini @@ -182,6 +182,120 @@ [:colorAttachmentsCountVariant={"mult":1,"add":1}] +[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,loadOp_storeOp:*] + implementation-status: backlog + [:format="bgra8unorm"] + expected: FAIL + + [:format="bgra8unorm-srgb"] + expected: FAIL + + [:format="r16float"] + expected: FAIL + + [:format="r16sint"] + expected: FAIL + + [:format="r16snorm"] + + [:format="r16uint"] + expected: FAIL + + [:format="r16unorm"] + + [:format="r32float"] + expected: FAIL + + [:format="r32sint"] + expected: FAIL + + [:format="r32uint"] + expected: FAIL + + [:format="r8sint"] + expected: FAIL + + [:format="r8uint"] + expected: FAIL + + [:format="r8unorm"] + expected: FAIL + + [:format="rg11b10ufloat"] + expected: FAIL + + [:format="rg16float"] + expected: FAIL + + [:format="rg16sint"] + expected: FAIL + + [:format="rg16snorm"] + + [:format="rg16uint"] + expected: FAIL + + [:format="rg16unorm"] + + [:format="rg32float"] + expected: FAIL + + [:format="rg32sint"] + expected: FAIL + + [:format="rg32uint"] + expected: FAIL + + [:format="rg8sint"] + expected: FAIL + + [:format="rg8uint"] + expected: FAIL + + [:format="rg8unorm"] + expected: FAIL + + [:format="rgb10a2uint"] + expected: FAIL + + [:format="rgb10a2unorm"] + expected: FAIL + + [:format="rgba16float"] + expected: FAIL + + [:format="rgba16sint"] + expected: FAIL + + [:format="rgba16snorm"] + + [:format="rgba16uint"] + expected: FAIL + + [:format="rgba16unorm"] + + [:format="rgba32float"] + expected: FAIL + + [:format="rgba32sint"] + expected: FAIL + + [:format="rgba32uint"] + expected: FAIL + + [:format="rgba8sint"] + expected: FAIL + + [:format="rgba8uint"] + expected: FAIL + + [:format="rgba8unorm"] + expected: FAIL + + [:format="rgba8unorm-srgb"] + expected: FAIL + + [cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,non_multisampled:*] [:] @@ -231,6 +345,8 @@ [cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:depth_stencil_attachment,loadOp_storeOp_match_depthReadOnly_stencilReadOnly:*] tags: [webgpu, webgpu-long] implementation-status: backlog + expected: + if os == "mac": TIMEOUT [:format="depth16unorm"] expected: FAIL @@ -238,11 +354,19 @@ expected: FAIL [:format="depth24plus-stencil8"] + expected: + if os == "win": FAIL + if os == "linux": FAIL + if os == "mac": [TIMEOUT, NOTRUN] [:format="depth32float"] expected: FAIL [:format="depth32float-stencil8"] + expected: + if os == "win": FAIL + if os == "linux": FAIL + if os == "mac": [TIMEOUT, NOTRUN] [:format="stencil8"] expected: FAIL diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/resource_usages/texture/in_render_misc/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/resource_usages/texture/in_render_misc/cts.https.html.ini @@ -266,6 +266,9 @@ [:bindingType="color-attachment";viewUsage=2] expected: FAIL + [:bindingType="color-attachment";viewUsage=32] + expected: FAIL + [:bindingType="color-attachment";viewUsage=4] expected: FAIL @@ -283,6 +286,9 @@ [:bindingType="readonly-storage-texture";viewUsage=2] expected: FAIL + [:bindingType="readonly-storage-texture";viewUsage=32] + expected: FAIL + [:bindingType="readonly-storage-texture";viewUsage=4] expected: FAIL @@ -299,6 +305,9 @@ [:bindingType="readwrite-storage-texture";viewUsage=2] expected: FAIL + [:bindingType="readwrite-storage-texture";viewUsage=32] + expected: FAIL + [:bindingType="readwrite-storage-texture";viewUsage=4] expected: FAIL @@ -315,6 +324,9 @@ [:bindingType="sampled-texture";viewUsage=2] expected: FAIL + [:bindingType="sampled-texture";viewUsage=32] + expected: FAIL + [:bindingType="sampled-texture";viewUsage=4] [:bindingType="sampled-texture";viewUsage=8] @@ -331,6 +343,9 @@ [:bindingType="writeonly-storage-texture";viewUsage=2] expected: FAIL + [:bindingType="writeonly-storage-texture";viewUsage=32] + expected: FAIL + [:bindingType="writeonly-storage-texture";viewUsage=4] expected: FAIL diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/state/device_lost/destroy/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/state/device_lost/destroy/cts.https.html.ini @@ -4623,6 +4623,7 @@ [:format="rg8sint";usageType="texture";usageCopy="none";awaitLost=true] expected: + if os == "win" and not debug: [PASS, TIMEOUT, NOTRUN] if os == "mac": [PASS, TIMEOUT, NOTRUN] [:format="rg8sint";usageType="texture";usageCopy="src";awaitLost=false] @@ -4703,10 +4704,12 @@ [:format="rg8uint";usageType="render";usageCopy="dst";awaitLost=false] expected: + if os == "win" and not debug: [PASS, TIMEOUT, NOTRUN] if os == "mac": [PASS, TIMEOUT, NOTRUN] [:format="rg8uint";usageType="render";usageCopy="dst";awaitLost=true] expected: + if os == "win" and not debug: [PASS, TIMEOUT, NOTRUN] if os == "mac": [PASS, TIMEOUT, NOTRUN] [:format="rg8uint";usageType="render";usageCopy="none";awaitLost=false] @@ -4727,10 +4730,12 @@ [:format="rg8uint";usageType="render";usageCopy="src-dest";awaitLost=false] expected: + if os == "win" and not debug: [PASS, TIMEOUT, NOTRUN] if os == "mac": [PASS, TIMEOUT, NOTRUN] [:format="rg8uint";usageType="render";usageCopy="src-dest";awaitLost=true] expected: + if os == "win" and not debug: [PASS, TIMEOUT, NOTRUN] if os == "mac": [PASS, TIMEOUT, NOTRUN] [:format="rg8uint";usageType="storage";usageCopy="dst";awaitLost=false] @@ -5633,15 +5638,13 @@ [:format="rgba8sint";usageType="storage";usageCopy="none";awaitLost=false] expected: - if os == "win" and debug: [PASS, TIMEOUT, NOTRUN] - if os == "win" and not debug: [FAIL, TIMEOUT, NOTRUN] + if os == "win": [FAIL, TIMEOUT, NOTRUN] if os == "linux": [PASS, TIMEOUT, NOTRUN] if os == "mac": [TIMEOUT, NOTRUN] [:format="rgba8sint";usageType="storage";usageCopy="none";awaitLost=true] expected: - if os == "win" and debug: [PASS, TIMEOUT, NOTRUN] - if os == "win" and not debug: [FAIL, TIMEOUT, NOTRUN] + if os == "win": [FAIL, TIMEOUT, NOTRUN] if os == "linux": [PASS, TIMEOUT, NOTRUN] if os == "mac": [TIMEOUT, NOTRUN] @@ -5653,8 +5656,7 @@ [:format="rgba8sint";usageType="storage";usageCopy="src";awaitLost=true] expected: - if os == "win" and debug: [PASS, TIMEOUT, NOTRUN] - if os == "win" and not debug: [FAIL, TIMEOUT, NOTRUN] + if os == "win": [FAIL, TIMEOUT, NOTRUN] if os == "linux": [PASS, TIMEOUT, NOTRUN] if os == "mac": [TIMEOUT, NOTRUN] @@ -5717,8 +5719,7 @@ [:format="rgba8sint";usageType="texture";usageCopy="src-dest";awaitLost=false] expected: - if os == "win" and debug: [PASS, TIMEOUT, NOTRUN] - if os == "win" and not debug: [FAIL, TIMEOUT, NOTRUN] + if os == "win": [FAIL, TIMEOUT, NOTRUN] if os == "linux": [PASS, TIMEOUT, NOTRUN] if os == "mac": [TIMEOUT, NOTRUN] @@ -8234,15 +8235,13 @@ [:format="r16sint";usageType="render";usageCopy="src";awaitLost=false] expected: - if os == "win" and debug: FAIL - if os == "win" and not debug: [FAIL, TIMEOUT, NOTRUN] + if os == "win": [FAIL, TIMEOUT, NOTRUN] if os == "linux": FAIL if os == "mac": [TIMEOUT, NOTRUN] [:format="r16sint";usageType="render";usageCopy="src";awaitLost=true] expected: - if os == "win" and debug: FAIL - if os == "win" and not debug: [FAIL, TIMEOUT, NOTRUN] + if os == "win": [FAIL, TIMEOUT, NOTRUN] if os == "linux": FAIL if os == "mac": [TIMEOUT, NOTRUN] diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/texture/bgra8unorm_storage/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/api/validation/texture/bgra8unorm_storage/cts.https.html.ini @@ -8,9 +8,15 @@ [cts.https.html?q=webgpu:api,validation,texture,bgra8unorm_storage:configure_storage_usage_on_canvas_context_without_bgra8unorm_storage:*] + implementation-status: + if os == "linux": backlog [:canvasType="offscreen"] + expected: + if os == "linux": FAIL [:canvasType="onscreen"] + expected: + if os == "linux": FAIL [cts.https.html?q=webgpu:api,validation,texture,bgra8unorm_storage:create_bind_group_layout:*] diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/constants/flags/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/constants/flags/cts.https.html.ini @@ -53,10 +53,13 @@ [cts.https.html?q=webgpu:idl,constants,flags:TextureUsage,count:*] + implementation-status: backlog [:] + expected: FAIL [cts.https.html?q=webgpu:idl,constants,flags:TextureUsage,values:*] + implementation-status: backlog [:key="COPY_DST"] [:key="COPY_SRC"] @@ -66,3 +69,6 @@ [:key="STORAGE_BINDING"] [:key="TEXTURE_BINDING"] + + [:key="TRANSIENT_ATTACHMENT"] + expected: FAIL diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/constants/flags/dedicated.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/constants/flags/dedicated.https.html.ini @@ -53,10 +53,13 @@ [dedicated.https.html?worker=dedicated&q=webgpu:idl,constants,flags:TextureUsage,count:*] + implementation-status: backlog [:] + expected: FAIL [dedicated.https.html?worker=dedicated&q=webgpu:idl,constants,flags:TextureUsage,values:*] + implementation-status: backlog [:key="COPY_DST"] [:key="COPY_SRC"] @@ -66,3 +69,6 @@ [:key="STORAGE_BINDING"] [:key="TEXTURE_BINDING"] + + [:key="TRANSIENT_ATTACHMENT"] + expected: FAIL diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/constants/flags/shared.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/constants/flags/shared.https.html.ini @@ -53,10 +53,13 @@ [shared.https.html?worker=shared&q=webgpu:idl,constants,flags:TextureUsage,count:*] + implementation-status: backlog [:] + expected: FAIL [shared.https.html?worker=shared&q=webgpu:idl,constants,flags:TextureUsage,values:*] + implementation-status: backlog [:key="COPY_DST"] [:key="COPY_SRC"] @@ -66,3 +69,6 @@ [:key="STORAGE_BINDING"] [:key="TEXTURE_BINDING"] + + [:key="TRANSIENT_ATTACHMENT"] + expected: FAIL diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/javascript/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/javascript/cts.https.html.ini @@ -15,15 +15,18 @@ [cts.https.html?q=webgpu:idl,javascript:getter_replacement:*] + implementation-status: backlog [:type="adapter"] [:type="adapter.limits"] + expected: FAIL [:type="buffer"] [:type="device"] [:type="device.limits"] + expected: FAIL [:type="gpu"] @@ -96,11 +99,11 @@ [cts.https.html?q=webgpu:idl,javascript:obj,for_in:*] - implementation-status: - if os == "linux": backlog + implementation-status: backlog [:type="adapter"] [:type="adapter.limits"] + expected: FAIL [:type="buffer"] @@ -109,6 +112,7 @@ if os == "linux": FAIL [:type="device.limits"] + expected: FAIL [:type="gpu"] @@ -172,15 +176,18 @@ [cts.https.html?q=webgpu:idl,javascript:readonly_properties:*] + implementation-status: backlog [:type="adapter"] [:type="adapter.limits"] + expected: FAIL [:type="buffer"] [:type="device"] [:type="device.limits"] + expected: FAIL [:type="gpu"] diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/javascript/dedicated.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/javascript/dedicated.https.html.ini @@ -15,15 +15,18 @@ [dedicated.https.html?worker=dedicated&q=webgpu:idl,javascript:getter_replacement:*] + implementation-status: backlog [:type="adapter"] [:type="adapter.limits"] + expected: FAIL [:type="buffer"] [:type="device"] [:type="device.limits"] + expected: FAIL [:type="gpu"] @@ -96,11 +99,11 @@ [dedicated.https.html?worker=dedicated&q=webgpu:idl,javascript:obj,for_in:*] - implementation-status: - if os == "linux": backlog + implementation-status: backlog [:type="adapter"] [:type="adapter.limits"] + expected: FAIL [:type="buffer"] @@ -109,6 +112,7 @@ if os == "linux": FAIL [:type="device.limits"] + expected: FAIL [:type="gpu"] @@ -172,15 +176,18 @@ [dedicated.https.html?worker=dedicated&q=webgpu:idl,javascript:readonly_properties:*] + implementation-status: backlog [:type="adapter"] [:type="adapter.limits"] + expected: FAIL [:type="buffer"] [:type="device"] [:type="device.limits"] + expected: FAIL [:type="gpu"] diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/javascript/shared.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/idl/javascript/shared.https.html.ini @@ -15,15 +15,18 @@ [shared.https.html?worker=shared&q=webgpu:idl,javascript:getter_replacement:*] + implementation-status: backlog [:type="adapter"] [:type="adapter.limits"] + expected: FAIL [:type="buffer"] [:type="device"] [:type="device.limits"] + expected: FAIL [:type="gpu"] @@ -96,11 +99,11 @@ [shared.https.html?worker=shared&q=webgpu:idl,javascript:obj,for_in:*] - implementation-status: - if os == "linux": backlog + implementation-status: backlog [:type="adapter"] [:type="adapter.limits"] + expected: FAIL [:type="buffer"] @@ -109,6 +112,7 @@ if os == "linux": FAIL [:type="device.limits"] + expected: FAIL [:type="gpu"] @@ -172,15 +176,18 @@ [shared.https.html?worker=shared&q=webgpu:idl,javascript:readonly_properties:*] + implementation-status: backlog [:type="adapter"] [:type="adapter.limits"] + expected: FAIL [:type="buffer"] [:type="device"] [:type="device.limits"] + expected: FAIL [:type="gpu"] diff --git a/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/shader/validation/uniformity/uniformity/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/cts/webgpu/shader/validation/uniformity/uniformity/cts.https.html.ini @@ -1,120 +1,680 @@ [cts.https.html?q=webgpu:shader,validation,uniformity,uniformity:basics,subgroups:*] - [:statement="break-if"] + [:statement="for-always-break-op"] - [:statement="for"] + [:statement="for-always-return-op"] - [:statement="for-with-cond-always-break-op-after"] + [:statement="for-cond-break-op"] - [:statement="for-with-cond-always-break-op-inside"] + [:statement="for-cond-return-op"] - [:statement="for-with-cond-always-return-op-after"] + [:statement="for-nonunif-always-break-end-op"] - [:statement="for-with-cond-always-return-op-inside"] + [:statement="for-nonunif-always-break-op"] - [:statement="for-without-cond-always-break-op-after"] + [:statement="for-nonunif-always-continue-end-op"] - [:statement="for-without-cond-always-break-op-inside"] + [:statement="for-nonunif-always-continue-op"] - [:statement="for-without-cond-always-return-op-after"] + [:statement="for-nonunif-always-return-end-op"] - [:statement="for-without-cond-always-return-op-inside"] + [:statement="for-nonunif-always-return-op"] + + [:statement="for-nonunif-cond-break-end-op"] + + [:statement="for-nonunif-cond-break-op"] + + [:statement="for-nonunif-cond-continue-end-op"] + + [:statement="for-nonunif-cond-continue-op"] + + [:statement="for-nonunif-cond-return-end-op"] + + [:statement="for-nonunif-cond-return-op"] + + [:statement="for-nonunif-end-op"] + + [:statement="for-nonunif-op"] + + [:statement="for-nonunif-op-always-break"] + + [:statement="for-nonunif-op-always-continue"] + + [:statement="for-nonunif-op-always-return"] + + [:statement="for-nonunif-op-cond-break"] + + [:statement="for-nonunif-op-cond-continue"] + + [:statement="for-nonunif-op-cond-return"] + + [:statement="for-op-always-break"] + + [:statement="for-op-always-return"] + + [:statement="for-op-cond-break"] + + [:statement="for-op-cond-return"] + + [:statement="for-op-unif-break-always-continue"] + + [:statement="for-op-unif-break-cond-continue"] + + [:statement="for-unif-always-break-end-op"] + + [:statement="for-unif-always-break-op"] + + [:statement="for-unif-always-continue-end-op"] + + [:statement="for-unif-always-continue-op"] + + [:statement="for-unif-always-return-end-op"] + + [:statement="for-unif-always-return-op"] + + [:statement="for-unif-cond-break-end-op"] + + [:statement="for-unif-cond-break-op"] + + [:statement="for-unif-cond-continue-end-op"] + + [:statement="for-unif-cond-continue-op"] + + [:statement="for-unif-cond-return-end-op"] + + [:statement="for-unif-cond-return-op"] + + [:statement="for-unif-end-op"] + + [:statement="for-unif-op"] + + [:statement="for-unif-op-always-break"] + + [:statement="for-unif-op-always-continue"] + + [:statement="for-unif-op-always-return"] + + [:statement="for-unif-op-cond-break"] + + [:statement="for-unif-op-cond-continue"] + + [:statement="for-unif-op-cond-return"] + + [:statement="for-unif-unif-break-always-continue-op"] + + [:statement="for-unif-unif-break-cond-continue-op"] [:statement="if"] - [:statement="loop-always-break-op-after"] + [:statement="loop-always-break-continuing-cond-break-end-op"] - [:statement="loop-always-break-op-continuing"] + [:statement="loop-always-break-continuing-end-op"] - [:statement="loop-always-break-op-inside"] + [:statement="loop-always-break-continuing-op"] - [:statement="loop-always-return-op-after"] + [:statement="loop-always-break-end-op"] - [:statement="loop-always-return-op-continuing"] + [:statement="loop-always-break-op"] - [:statement="loop-always-return-op-inside"] + [:statement="loop-always-return-continuing-cond-break-end-op"] + + [:statement="loop-always-return-continuing-end-op"] + + [:statement="loop-always-return-continuing-op"] + + [:statement="loop-always-return-end-op"] + + [:statement="loop-always-return-op"] + + [:statement="loop-cond-break-continuing-end-op"] + + [:statement="loop-cond-break-continuing-op"] + + [:statement="loop-cond-break-end-op"] + + [:statement="loop-cond-break-op"] + + [:statement="loop-cond-return-continuing-end-op"] + + [:statement="loop-cond-return-continuing-op"] + + [:statement="loop-cond-return-end-op"] + + [:statement="loop-cond-return-op"] + + [:statement="loop-continuing-cond-break-end-op"] + + [:statement="loop-continuing-op-cond-break"] + + [:statement="loop-op-always-break"] + + [:statement="loop-op-always-break-continuing"] + + [:statement="loop-op-always-return"] + + [:statement="loop-op-always-return-continuing"] + + [:statement="loop-op-cond-break"] + + [:statement="loop-op-cond-break-continuing"] + + [:statement="loop-op-cond-return"] + + [:statement="loop-op-cond-return-continuing"] + + [:statement="loop-op-continuing-cond-break"] + + [:statement="loop-op-unif-break-continuing"] + + [:statement="loop-unif-break-always-continue-continuing-end-op"] + + [:statement="loop-unif-break-always-continue-end-op"] + + [:statement="loop-unif-break-always-continue-op"] + + [:statement="loop-unif-break-cond-continue-continuing-end-op"] + + [:statement="loop-unif-break-cond-continue-end-op"] + + [:statement="loop-unif-break-cond-continue-op"] + + [:statement="loop-unif-break-end-op"] + + [:statement="loop-unif-break-op-always-continue"] + + [:statement="loop-unif-break-op-always-continue-continuing"] + + [:statement="loop-unif-break-op-cond-continue"] + + [:statement="loop-unif-break-op-cond-continue-continuing"] [:statement="switch"] - [:statement="while"] + [:statement="while-nonunif-always-break-end-op"] + + [:statement="while-nonunif-always-break-op"] + + [:statement="while-nonunif-always-continue-end-op"] + + [:statement="while-nonunif-always-continue-op"] + + [:statement="while-nonunif-always-return-end-op"] + + [:statement="while-nonunif-always-return-op"] + + [:statement="while-nonunif-cond-break-end-op"] + + [:statement="while-nonunif-cond-break-op"] - [:statement="while-always-break-op-after"] + [:statement="while-nonunif-cond-continue-end-op"] - [:statement="while-always-break-op-inside"] + [:statement="while-nonunif-cond-continue-op"] - [:statement="while-always-return-op-after"] + [:statement="while-nonunif-cond-return-end-op"] - [:statement="while-always-return-op-inside"] + [:statement="while-nonunif-cond-return-op"] + + [:statement="while-nonunif-end-op"] + + [:statement="while-nonunif-op"] + + [:statement="while-nonunif-op-always-break"] + + [:statement="while-nonunif-op-always-continue"] + + [:statement="while-nonunif-op-always-return"] + + [:statement="while-nonunif-op-cond-break"] + + [:statement="while-nonunif-op-cond-continue"] + + [:statement="while-nonunif-op-cond-return"] + + [:statement="while-unif-always-break-end-op"] + + [:statement="while-unif-always-break-op"] + + [:statement="while-unif-always-continue-end-op"] + + [:statement="while-unif-always-continue-op"] + + [:statement="while-unif-always-return-end-op"] + + [:statement="while-unif-always-return-op"] + + [:statement="while-unif-cond-break-end-op"] + + [:statement="while-unif-cond-break-op"] + + [:statement="while-unif-cond-continue-end-op"] + + [:statement="while-unif-cond-continue-op"] + + [:statement="while-unif-cond-return-end-op"] + + [:statement="while-unif-cond-return-op"] + + [:statement="while-unif-end-op"] + + [:statement="while-unif-op"] + + [:statement="while-unif-op-always-break"] + + [:statement="while-unif-op-always-continue"] + + [:statement="while-unif-op-always-return"] + + [:statement="while-unif-op-cond-break"] + + [:statement="while-unif-op-cond-continue"] + + [:statement="while-unif-op-cond-return"] [cts.https.html?q=webgpu:shader,validation,uniformity,uniformity:basics:*] implementation-status: backlog - [:statement="break-if"] + [:statement="for-always-break-op"] + expected: FAIL + + [:statement="for-always-return-op"] + expected: FAIL + + [:statement="for-cond-break-op"] + expected: FAIL + + [:statement="for-cond-return-op"] + expected: FAIL + + [:statement="for-nonunif-always-break-end-op"] + expected: FAIL + + [:statement="for-nonunif-always-break-op"] + expected: FAIL + + [:statement="for-nonunif-always-continue-end-op"] + expected: FAIL + + [:statement="for-nonunif-always-continue-op"] + expected: FAIL + + [:statement="for-nonunif-always-return-end-op"] + expected: FAIL + + [:statement="for-nonunif-always-return-op"] + expected: FAIL + + [:statement="for-nonunif-cond-break-end-op"] + expected: FAIL + + [:statement="for-nonunif-cond-break-op"] + expected: FAIL + + [:statement="for-nonunif-cond-continue-end-op"] + expected: FAIL + + [:statement="for-nonunif-cond-continue-op"] + expected: FAIL + + [:statement="for-nonunif-cond-return-end-op"] + expected: FAIL + + [:statement="for-nonunif-cond-return-op"] + expected: FAIL + + [:statement="for-nonunif-end-op"] + expected: FAIL + + [:statement="for-nonunif-op"] + expected: FAIL + + [:statement="for-nonunif-op-always-break"] + expected: FAIL + + [:statement="for-nonunif-op-always-continue"] + expected: FAIL + + [:statement="for-nonunif-op-always-return"] + expected: FAIL + + [:statement="for-nonunif-op-cond-break"] + expected: FAIL + + [:statement="for-nonunif-op-cond-continue"] + expected: FAIL + + [:statement="for-nonunif-op-cond-return"] + expected: FAIL + + [:statement="for-op-always-break"] + expected: FAIL + + [:statement="for-op-always-return"] + expected: FAIL + + [:statement="for-op-cond-break"] + expected: FAIL + + [:statement="for-op-cond-return"] + expected: FAIL + + [:statement="for-op-unif-break-always-continue"] expected: FAIL - [:statement="for"] + [:statement="for-op-unif-break-cond-continue"] expected: FAIL - [:statement="for-with-cond-always-break-op-after"] + [:statement="for-unif-always-break-end-op"] expected: FAIL - [:statement="for-with-cond-always-break-op-inside"] + [:statement="for-unif-always-break-op"] expected: FAIL - [:statement="for-with-cond-always-return-op-after"] + [:statement="for-unif-always-continue-end-op"] expected: FAIL - [:statement="for-with-cond-always-return-op-inside"] + [:statement="for-unif-always-continue-op"] expected: FAIL - [:statement="for-without-cond-always-break-op-after"] + [:statement="for-unif-always-return-end-op"] expected: FAIL - [:statement="for-without-cond-always-break-op-inside"] + [:statement="for-unif-always-return-op"] expected: FAIL - [:statement="for-without-cond-always-return-op-after"] + [:statement="for-unif-cond-break-end-op"] expected: FAIL - [:statement="for-without-cond-always-return-op-inside"] + [:statement="for-unif-cond-break-op"] + expected: FAIL + + [:statement="for-unif-cond-continue-end-op"] + expected: FAIL + + [:statement="for-unif-cond-continue-op"] + expected: FAIL + + [:statement="for-unif-cond-return-end-op"] + expected: FAIL + + [:statement="for-unif-cond-return-op"] + expected: FAIL + + [:statement="for-unif-end-op"] + expected: FAIL + + [:statement="for-unif-op"] + expected: FAIL + + [:statement="for-unif-op-always-break"] + expected: FAIL + + [:statement="for-unif-op-always-continue"] + expected: FAIL + + [:statement="for-unif-op-always-return"] + expected: FAIL + + [:statement="for-unif-op-cond-break"] + expected: FAIL + + [:statement="for-unif-op-cond-continue"] + expected: FAIL + + [:statement="for-unif-op-cond-return"] + expected: FAIL + + [:statement="for-unif-unif-break-always-continue-op"] + expected: FAIL + + [:statement="for-unif-unif-break-cond-continue-op"] expected: FAIL [:statement="if"] expected: FAIL - [:statement="loop-always-break-op-after"] + [:statement="loop-always-break-continuing-cond-break-end-op"] + expected: FAIL + + [:statement="loop-always-break-continuing-end-op"] + expected: FAIL + + [:statement="loop-always-break-continuing-op"] + expected: FAIL + + [:statement="loop-always-break-end-op"] + expected: FAIL + + [:statement="loop-always-break-op"] + expected: FAIL + + [:statement="loop-always-return-continuing-cond-break-end-op"] + expected: FAIL + + [:statement="loop-always-return-continuing-end-op"] + expected: FAIL + + [:statement="loop-always-return-continuing-op"] + expected: FAIL + + [:statement="loop-always-return-end-op"] + expected: FAIL + + [:statement="loop-always-return-op"] + expected: FAIL + + [:statement="loop-cond-break-continuing-end-op"] + expected: FAIL + + [:statement="loop-cond-break-continuing-op"] + expected: FAIL + + [:statement="loop-cond-break-end-op"] + expected: FAIL + + [:statement="loop-cond-break-op"] + expected: FAIL + + [:statement="loop-cond-return-continuing-end-op"] + expected: FAIL + + [:statement="loop-cond-return-continuing-op"] + expected: FAIL + + [:statement="loop-cond-return-end-op"] + expected: FAIL + + [:statement="loop-cond-return-op"] + expected: FAIL + + [:statement="loop-continuing-cond-break-end-op"] + expected: FAIL + + [:statement="loop-continuing-op-cond-break"] + expected: FAIL + + [:statement="loop-op-always-break"] + expected: FAIL + + [:statement="loop-op-always-break-continuing"] + expected: FAIL + + [:statement="loop-op-always-return"] + expected: FAIL + + [:statement="loop-op-always-return-continuing"] + expected: FAIL + + [:statement="loop-op-cond-break"] + expected: FAIL + + [:statement="loop-op-cond-break-continuing"] + expected: FAIL + + [:statement="loop-op-cond-return"] + expected: FAIL + + [:statement="loop-op-cond-return-continuing"] + expected: FAIL + + [:statement="loop-op-continuing-cond-break"] expected: FAIL - [:statement="loop-always-break-op-continuing"] + [:statement="loop-op-unif-break-continuing"] expected: FAIL - [:statement="loop-always-break-op-inside"] + [:statement="loop-unif-break-always-continue-continuing-end-op"] expected: FAIL - [:statement="loop-always-return-op-after"] + [:statement="loop-unif-break-always-continue-end-op"] expected: FAIL - [:statement="loop-always-return-op-continuing"] + [:statement="loop-unif-break-always-continue-op"] expected: FAIL - [:statement="loop-always-return-op-inside"] + [:statement="loop-unif-break-cond-continue-continuing-end-op"] + expected: FAIL + + [:statement="loop-unif-break-cond-continue-end-op"] + expected: FAIL + + [:statement="loop-unif-break-cond-continue-op"] + expected: FAIL + + [:statement="loop-unif-break-end-op"] + expected: FAIL + + [:statement="loop-unif-break-op-always-continue"] + expected: FAIL + + [:statement="loop-unif-break-op-always-continue-continuing"] + expected: FAIL + + [:statement="loop-unif-break-op-cond-continue"] + expected: FAIL + + [:statement="loop-unif-break-op-cond-continue-continuing"] expected: FAIL [:statement="switch"] expected: FAIL - [:statement="while"] + [:statement="while-nonunif-always-break-end-op"] + expected: FAIL + + [:statement="while-nonunif-always-break-op"] + expected: FAIL + + [:statement="while-nonunif-always-continue-end-op"] + expected: FAIL + + [:statement="while-nonunif-always-continue-op"] + expected: FAIL + + [:statement="while-nonunif-always-return-end-op"] + expected: FAIL + + [:statement="while-nonunif-always-return-op"] + expected: FAIL + + [:statement="while-nonunif-cond-break-end-op"] + expected: FAIL + + [:statement="while-nonunif-cond-break-op"] + expected: FAIL + + [:statement="while-nonunif-cond-continue-end-op"] + expected: FAIL + + [:statement="while-nonunif-cond-continue-op"] + expected: FAIL + + [:statement="while-nonunif-cond-return-end-op"] + expected: FAIL + + [:statement="while-nonunif-cond-return-op"] + expected: FAIL + + [:statement="while-nonunif-end-op"] + expected: FAIL + + [:statement="while-nonunif-op"] + expected: FAIL + + [:statement="while-nonunif-op-always-break"] + expected: FAIL + + [:statement="while-nonunif-op-always-continue"] + expected: FAIL + + [:statement="while-nonunif-op-always-return"] + expected: FAIL + + [:statement="while-nonunif-op-cond-break"] + expected: FAIL + + [:statement="while-nonunif-op-cond-continue"] + expected: FAIL + + [:statement="while-nonunif-op-cond-return"] + expected: FAIL + + [:statement="while-unif-always-break-end-op"] + expected: FAIL + + [:statement="while-unif-always-break-op"] + expected: FAIL + + [:statement="while-unif-always-continue-end-op"] + expected: FAIL + + [:statement="while-unif-always-continue-op"] + expected: FAIL + + [:statement="while-unif-always-return-end-op"] + expected: FAIL + + [:statement="while-unif-always-return-op"] + expected: FAIL + + [:statement="while-unif-cond-break-end-op"] + expected: FAIL + + [:statement="while-unif-cond-break-op"] + expected: FAIL + + [:statement="while-unif-cond-continue-end-op"] + expected: FAIL + + [:statement="while-unif-cond-continue-op"] + expected: FAIL + + [:statement="while-unif-cond-return-end-op"] + expected: FAIL + + [:statement="while-unif-cond-return-op"] + expected: FAIL + + [:statement="while-unif-end-op"] + expected: FAIL + + [:statement="while-unif-op"] + expected: FAIL + + [:statement="while-unif-op-always-break"] + expected: FAIL + + [:statement="while-unif-op-always-continue"] expected: FAIL - [:statement="while-always-break-op-after"] + [:statement="while-unif-op-always-return"] expected: FAIL - [:statement="while-always-break-op-inside"] + [:statement="while-unif-op-cond-break"] expected: FAIL - [:statement="while-always-return-op-after"] + [:statement="while-unif-op-cond-continue"] expected: FAIL - [:statement="while-always-return-op-inside"] + [:statement="while-unif-op-cond-return"] expected: FAIL diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js @@ -1,3 +1,3 @@ // AUTO-GENERATED - DO NOT EDIT. See tools/gen_version. -export const version = 'ef27c0b88b802ca64677e2c0ed60378951ac6c42'; +export const version = 'f7d27f91423683338da291a4a8bdb10dabebb42d'; diff --git a/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pass/render_pass_descriptor/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/cts/webgpu/api/validation/render_pass/render_pass_descriptor/cts.https.html @@ -47,6 +47,7 @@ <meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,limits,maxColorAttachmentBytesPerSample,aligned:*'> <meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,limits,maxColorAttachmentBytesPerSample,unaligned:*'> <meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,limits,maxColorAttachments:*'> +<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,loadOp_storeOp:*'> <meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,non_multisampled:*'> <meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,sample_count:*'> <meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:depth_stencil_attachment,depth_clear_value:*'> diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroup.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroup.spec.js @@ -22,7 +22,8 @@ import { kTextureUsages, kTextureViewDimensions, sampledAndStorageBindingEntries, - texBindingTypeInfo } from + texBindingTypeInfo, + IsValidTransientAttachmentUsage } from '../../capability_info.js'; import { GPUConst } from '../../constants.js'; import { kPossibleStorageTextureFormats, kRegularTextureFormats } from '../../format_info.js'; @@ -199,6 +200,13 @@ u // combine('usage', kTextureUsages). unless(({ entry, usage }) => { const info = texBindingTypeInfo(entry); + // TRANSIENT_ATTACHMENT is only valid when combined with RENDER_ATTACHMENT, so skip. + if ( + usage === GPUConst.TextureUsage.TRANSIENT_ATTACHMENT && + info.resource !== 'sampledTexMS') + { + return true; + } // Can't create the texture for this (usage=STORAGE_BINDING and sampleCount=4), so skip. return usage === GPUConst.TextureUsage.STORAGE_BINDING && info.resource === 'sampledTexMS'; }) @@ -780,7 +788,14 @@ u // // If usage0 and usage1 are the same, the usage being test is a single usage. Otherwise, it's // a combined usage. .combine('usage0', kTextureUsages). -combine('usage1', kTextureUsages) +combine('usage1', kTextureUsages). +unless(({ usage0, usage1 }) => { + const usage = usage0 | usage1; + return ( + (usage & GPUConst.TextureUsage.TRANSIENT_ATTACHMENT) !== 0 && + !IsValidTransientAttachmentUsage(usage)); + +}) ). fn((t) => { const { usage0, usage1 } = t.params; @@ -1211,7 +1226,14 @@ u // // If usage0 and usage1 are the same, the usage being test is a single usage. Otherwise, it's // a combined usage. .combine('usage0', kTextureUsages). -combine('usage1', kTextureUsages) +combine('usage1', kTextureUsages). +unless(({ usage0, usage1 }) => { + const usage = usage0 | usage1; + return ( + (usage & GPUConst.TextureUsage.TRANSIENT_ATTACHMENT) !== 0 && + !IsValidTransientAttachmentUsage(usage)); + +}) ). fn((t) => { const { usage0, usage1 } = t.params; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createTexture.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createTexture.spec.js @@ -3,7 +3,11 @@ **/export const description = `createTexture validation tests.`;import { AllFeaturesMaxLimitsGPUTest } from '../.././gpu_test.js'; import { makeTestGroup } from '../../../common/framework/test_group.js'; import { assert, makeValueTestVariant } from '../../../common/util/util.js'; -import { kTextureDimensions, kTextureUsages } from '../../capability_info.js'; +import { + kTextureDimensions, + kTextureUsages, + IsValidTransientAttachmentUsage } from +'../../capability_info.js'; import { GPUConst } from '../../constants.js'; import { kAllTextureFormats, @@ -343,7 +347,11 @@ unless(({ usage, format, mipLevelCount, dimension }) => { dimension !== '2d') || (usage & GPUConst.TextureUsage.STORAGE_BINDING) !== 0 && !isTextureFormatPossiblyStorageReadable(format) || - mipLevelCount !== 1 && dimension === '1d'); + mipLevelCount !== 1 && dimension === '1d' || + (usage & GPUConst.TextureUsage.TRANSIENT_ATTACHMENT) !== 0 && + usage !== ( + GPUConst.TextureUsage.RENDER_ATTACHMENT | + GPUConst.TextureUsage.TRANSIENT_ATTACHMENT)); }) ). @@ -1007,7 +1015,14 @@ combine('usage1', kTextureUsages) // Filter out incompatible dimension type and format combinations. .filter(({ dimension, format }) => textureFormatAndDimensionPossiblyCompatible(dimension, format) -) +). +unless(({ usage0, usage1 }) => { + const usage = usage0 | usage1; + return ( + (usage & GPUConst.TextureUsage.TRANSIENT_ATTACHMENT) !== 0 && + !IsValidTransientAttachmentUsage(usage)); + +}) ). fn((t) => { const { dimension, format, usage0, usage1 } = t.params; @@ -1037,6 +1052,11 @@ fn((t) => { if (isColorTextureFormat(format) && !isTextureFormatColorRenderable(t.device, format)) success = false; } + if (usage & GPUTextureUsage.TRANSIENT_ATTACHMENT) { + if (usage !== (GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TRANSIENT_ATTACHMENT)) { + success = false; + } + } t.expectValidationError(() => { t.createTextureTracked(descriptor); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createView.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createView.spec.js @@ -356,7 +356,14 @@ unless(({ format, textureUsage }) => { }). beginSubcases(). -combine('textureViewUsage', [0, ...kTextureUsages]) +combine('textureViewUsage', [0, ...kTextureUsages]). +unless(({ textureUsage, textureViewUsage }) => { + // TRANSIENT_ATTACHMENT is only valid when combined with RENDER_ATTACHMENT. + return ( + textureUsage === GPUConst.TextureUsage.TRANSIENT_ATTACHMENT || + textureViewUsage === GPUConst.TextureUsage.TRANSIENT_ATTACHMENT); + +}) ). fn((t) => { const { format, textureUsage, textureViewUsage } = t.params; @@ -393,7 +400,11 @@ u. combine('textureFormat', kAllTextureFormats). combine('usage', kTextureUsages). beginSubcases(). -combine('viewFormat', kAllTextureFormats) +combine('viewFormat', kAllTextureFormats). +unless(({ usage }) => { + // TRANSIENT_ATTACHMENT is only valid when combined with RENDER_ATTACHMENT. + return usage === GPUConst.TextureUsage.TRANSIENT_ATTACHMENT; +}) ). fn((t) => { const { textureFormat, viewFormat, usage } = t.params; diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/encoder_open_state.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/encoder_open_state.spec.js @@ -98,6 +98,7 @@ const kRenderPassEncoderCommandInfo = setScissorRect: {}, setBlendConstant: {}, setStencilReference: {}, + setImmediates: {}, beginOcclusionQuery: {}, endOcclusionQuery: {}, executeBundles: {}, @@ -122,6 +123,7 @@ const kRenderBundleEncoderCommandInfo = setBindGroup: {}, setIndexBuffer: {}, setVertexBuffer: {}, + setImmediates: {}, pushDebugGroup: {}, popDebugGroup: {}, insertDebugMarker: {} @@ -141,6 +143,7 @@ const kComputePassEncoderCommandInfo = setPipeline: {}, dispatchWorkgroups: {}, dispatchWorkgroupsIndirect: {}, + setImmediates: {}, pushDebugGroup: {}, popDebugGroup: {}, insertDebugMarker: {} @@ -391,6 +394,12 @@ fn((t) => { renderPass.setStencilReference(0); } break; + case 'setImmediates': + { + const data = new Uint32Array(1); + renderPass.setImmediates(0, data, 0, 1); + } + break; case 'beginOcclusionQuery': { renderPass.beginOcclusionQuery(0); @@ -502,6 +511,12 @@ fn((t) => { bundleEncoder.setVertexBuffer(1, buffer); } break; + case 'setImmediates': + { + const data = new Uint32Array(1); + bundleEncoder.setImmediates(0, data, 0, 1); + } + break; case 'pushDebugGroup': { bundleEncoder.pushDebugGroup('group'); @@ -584,6 +599,12 @@ fn((t) => { computePass.dispatchWorkgroupsIndirect(indirectBuffer, 0); } break; + case 'setImmediates': + { + const data = new Uint32Array(1); + computePass.setImmediates(0, data, 0, 1); + } + break; case 'pushDebugGroup': { computePass.pushDebugGroup('group'); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/render_pass_descriptor.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/render_pass_descriptor.spec.js @@ -718,6 +718,48 @@ fn((t) => { } }); +g.test('color_attachments,loadOp_storeOp'). +desc( + ` + Test GPURenderPassColorAttachment Usage: + - if usage includes TRANSIENT_ATTACHMENT + - loadOp must be clear + - storeOp must be discard + ` +). +params((u) => +u. +combine('format', kPossibleColorRenderableTextureFormats). +beginSubcases(). +combine('transientTexture', [true, false]). +combine('loadOp', ['clear', 'load']). +combine('storeOp', ['discard', 'store']) +). +fn((t) => { + const { format, transientTexture, loadOp, storeOp } = t.params; + + t.skipIfTextureFormatNotSupported(format); + t.skipIfTextureFormatNotUsableAsRenderAttachment(format); + + const usage = transientTexture ? + GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TRANSIENT_ATTACHMENT : + GPUTextureUsage.RENDER_ATTACHMENT; + + const texture = t.createTestTexture({ usage }); + + const colorAttachment = t.getColorAttachment(texture); + colorAttachment.loadOp = loadOp; + colorAttachment.storeOp = storeOp; + + const passDescriptor = { + colorAttachments: [colorAttachment] + }; + + const success = !transientTexture || loadOp === 'clear' && storeOp === 'discard'; + + t.tryRenderPass(success, passDescriptor); +}); + g.test('color_attachments,non_multisampled'). desc( ` @@ -1039,23 +1081,29 @@ g.test('depth_stencil_attachment,loadOp_storeOp_match_depthReadOnly_stencilReadO desc( ` Test GPURenderPassDepthStencilAttachment Usage: - - if the format has a depth aspect: - - if depthReadOnly is true - - depthLoadOp and depthStoreOp must not be provided - - else: - - depthLoadOp and depthStoreOp must be provided - - if the format has a stencil aspect: - - if stencilReadOnly is true - - stencilLoadOp and stencilStoreOp must not be provided - - else: - - stencilLoadOp and stencilStoreOp must be provided + - if the format has a depth aspect and depthReadOnly is false + - depthLoadOp and depthStoreOp must be provided + - else: + - depthLoadOp and depthStoreOp must not be provided + - if the format has a stencil aspect and stencilReadOnly is false + - stencilLoadOp and stencilStoreOp must be provided + - else: + - stencilLoadOp and stencilStoreOp must not be provided + - if usage includes TRANSIENT_ATTACHMENT + - if the format has a depth aspect: + - depthLoadOp must be clear + - depthStoreOp must be discard + - if the format has a stencil aspect: + - stencilLoadOp must be clear + - stencilStoreOp must be discard ` ). params((u) => u. combine('format', kDepthStencilFormats). beginSubcases() // Note: It's easier to debug if you comment this line out as you can then run an individual case. -.combine('depthReadOnly', [undefined, true, false]). +.combine('transientTexture', [true, false]). +combine('depthReadOnly', [undefined, true, false]). combine('depthLoadOp', [undefined, 'clear', 'load']). combine('depthStoreOp', [undefined, 'discard', 'store']). combine('stencilReadOnly', [undefined, true, false]). @@ -1065,6 +1113,7 @@ combine('stencilStoreOp', [undefined, 'discard', 'store']) fn((t) => { const { format, + transientTexture, depthReadOnly, depthLoadOp, depthStoreOp, @@ -1075,10 +1124,13 @@ fn((t) => { t.skipIfTextureFormatNotSupported(format); + const usage = transientTexture ? + GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TRANSIENT_ATTACHMENT : + GPUTextureUsage.RENDER_ATTACHMENT; const depthAttachment = t.createTextureTracked({ format, size: { width: 1, height: 1, depthOrArrayLayers: 1 }, - usage: GPUTextureUsage.RENDER_ATTACHMENT + usage }); const depthAttachmentView = depthAttachment.createView(); @@ -1120,7 +1172,13 @@ fn((t) => { const goodStencilCombo = hasStencil && !stencilReadOnly ? hasBothStencilOps : hasNeitherStencilOps; - const shouldError = !goodAspectSettingsPresent || !goodDepthCombo || !goodStencilCombo; + const goodTransient = + !transientTexture || + (!hasDepth || depthLoadOp === 'clear' && depthStoreOp === 'discard') && ( + !hasStencil || stencilLoadOp === 'clear' && stencilStoreOp === 'discard'); + + const shouldError = + !goodAspectSettingsPresent || !goodDepthCombo || !goodStencilCombo || !goodTransient; t.expectValidationError(() => { encoder.finish(); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/capability_info.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/capability_info.js @@ -209,11 +209,19 @@ export const kTextureUsageInfo = [GPUConst.TextureUsage.COPY_DST]: {}, [GPUConst.TextureUsage.TEXTURE_BINDING]: {}, [GPUConst.TextureUsage.STORAGE_BINDING]: {}, - [GPUConst.TextureUsage.RENDER_ATTACHMENT]: {} + [GPUConst.TextureUsage.RENDER_ATTACHMENT]: {}, + [GPUConst.TextureUsage.TRANSIENT_ATTACHMENT]: {} }; /** List of all GPUTextureUsage values. */ export const kTextureUsages = numericKeysOf(kTextureUsageInfo); +/** Check if `usage` is TRANSIENT_ATTACHMENT | RENDER_ATTACHMENT. */ +export function IsValidTransientAttachmentUsage(usage) { + return ( + usage === (GPUConst.TextureUsage.TRANSIENT_ATTACHMENT | GPUConst.TextureUsage.RENDER_ATTACHMENT)); + +} + // Texture View /** Per-GPUTextureViewDimension info. */ @@ -767,7 +775,8 @@ const [kLimitInfoKeys, kLimitInfoDefaults, kLimitInfoData] = 'maxComputeWorkgroupSizeX': [, 256, 128], 'maxComputeWorkgroupSizeY': [, 256, 128], 'maxComputeWorkgroupSizeZ': [, 64, 64], - 'maxComputeWorkgroupsPerDimension': [, 65535, 65535] + 'maxComputeWorkgroupsPerDimension': [, 65535, 65535], + 'maxImmediateSize': [, 64, 64] }]; // MAINTENANCE_TODO: Remove when the compat spec is merged. diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/constants.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/constants.js @@ -17,6 +17,13 @@ const BufferUsage = { }; checkType(BufferUsage); + + + + + + + const TextureUsage = { COPY_SRC: 0x01, COPY_DST: 0x02, @@ -24,7 +31,8 @@ const TextureUsage = { SAMPLED: 0x04, STORAGE_BINDING: 0x08, STORAGE: 0x08, - RENDER_ATTACHMENT: 0x10 + RENDER_ATTACHMENT: 0x10, + TRANSIENT_ATTACHMENT: 0x20 }; checkType(TextureUsage); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/constants/flags.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/constants/flags.spec.js @@ -34,7 +34,8 @@ const kTextureUsageExp = { COPY_DST: 0x02, TEXTURE_BINDING: 0x04, STORAGE_BINDING: 0x08, - RENDER_ATTACHMENT: 0x10 + RENDER_ATTACHMENT: 0x10, + TRANSIENT_ATTACHMENT: 0x20 }; g.test('TextureUsage,count').fn((t) => { t.assertMemberCount(GPUTextureUsage, kTextureUsageExp); diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/uniformity/snippet.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/uniformity/snippet.js @@ -0,0 +1,186 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export const description = 'Utilities for generating code snippets for uniformity tests';import { assert, unreachable } from '../../../../common/util/util.js'; + + + + + + + + + + + + + + +export function compileShouldSucceed({ + requires_uniformity, + condition_is_uniform, + verdict + + + + +}) { + switch (verdict) { + case 'sensitive': + return !requires_uniformity || condition_is_uniform; + case 'forbid': + return !requires_uniformity; + case 'permit': + return true; + } +} + + + + + + + + + + + + + +// We use a small domain-specific language that converts a +// string into a code snippet. +// +// NOTE: If you're confused about this scheme, see the unit tests +// in src/unittests/uniformity_snippet.spec.ts. Run them +// with `npm run unittest`. +// +// We process the name from left to right +// using the following component naming scheme: +// <kind-of-loop>, always appears first +// 'loop' +// 'for', for-loop with without a condition +// 'for-unif', for-loop with a uniform loop condition +// 'for-nonunif', for-loop with a non-uniform loop condition +// 'while-unif', while-loop with uniform loop condition +// 'while-nonunif', while-loop with non-uniform loop condition +// The next components are listed in order they appear in the code. +// <interrupt> : +// always-break, cond-break, +// always-return, cond-return, +// always-continue, cond-continue, +// The 'cond' variations will use a condition, either uniform +// or non-uniform, to be substituted later. +// 'unif-break': a loop break with uniform loop condition, used +// to avoid rejection due to infinite loop checks. +// 'op': +// 'continuing': indicates start of continuing block +// 'end': indicates end of the loop + + + +// Expand a loop case spec to its shader code +export function specToCode(spec) { + let matches = spec.match('^(loop|for-unif|for-nonunif|for|while-unif|while-nonunif)-(.*)'); + assert(matches !== null, `invalid spec string: ${spec}`); + + let prefix = ' '; + const parts = []; + const end_parts = [prefix, '}\n']; // closing brace + + const kind = matches[1]; + let rest = matches[2]; + parts.push(prefix); + switch (kind) { + case 'loop': + parts.push('loop {'); + break; + case 'for': + parts.push('for (;;) {'); + break; + case 'for-unif': + parts.push(`for (;<uniform_cond>;) {`); + break; + case 'for-nonunif': + parts.push(`for (;<nonuniform_cond>;) {`); + break; + case 'while-unif': + parts.push(`while (<uniform_cond>) {`); + break; + case 'while-nonunif': + parts.push(`while (<nonuniform_cond>) {`); + break; + } + parts.push('\n'); + + let in_continuing = false; + prefix = ' '; + while (rest.length > 0) { + const current_len = rest.length; + matches = rest.match( + '^(op|continuing|end|unif-break|always-break|cond-break|unif-break|always-return|cond-return|always-continue|cond-continue)(-|$)(.*)' + ); + assert(matches !== null, `invalid spec string: ${spec}`); + const elem = matches[1]; + rest = matches[3]; + assert(rest.length < current_len, `pattern is not shrinking: '${rest}', from ${spec}`); + switch (elem) { + case 'op': + parts.push(prefix, '<op>\n'); // to be replaced later. + break; + case 'end': // end the loop + if (in_continuing) { + prefix = ' '; + } + prefix = ' '; + parts.push(...end_parts); + end_parts.length = 0; + in_continuing = false; + break; + case 'continuing': + parts.push(prefix, 'continuing {\n'); + end_parts.unshift(prefix, '}\n'); + in_continuing = true; + prefix = ' '; + break; + case 'unif-break': + assert(!in_continuing); + parts.push(prefix, `if <uniform_cond> {break;}\n`); + break; + case 'always-break': + assert(!in_continuing); + parts.push(prefix, 'break;\n'); + break; + case 'cond-break': + if (in_continuing) { + parts.push(prefix, `break if <cond>;\n`); + } else { + parts.push(prefix, `if <cond> {break;}\n`); + } + break; + case 'always-return': + assert(!in_continuing); + parts.push(prefix, 'return;\n'); + break; + case 'cond-return': + assert(!in_continuing); + parts.push(prefix, `if <cond> {return;}\n`); + break; + case 'always-continue': + assert(!in_continuing); + parts.push(prefix, 'continue;\n'); + break; + case 'cond-continue': + assert(!in_continuing); + parts.push(prefix, `if <cond> {continue;}\n`); + break; + default: + unreachable(`invalid loop case spec ${spec}`); + } + } + parts.push(...end_parts); + return parts.join(''); +} + +// Creates a Snippet from a loop spec string and a verdict. +export function LoopCase(spec, verdict) { + return { name: spec, verdict, code: specToCode(spec) }; +} +\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/uniformity/uniformity.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/uniformity/uniformity.spec.js @@ -5,6 +5,8 @@ import { keysOf } from '../../../../common/util/data_tables.js'; import { unreachable } from '../../../../common/util/util.js'; import { ShaderValidationTest } from '../shader_validation_test.js'; +import { LoopCase, compileShouldSucceed } from './snippet.js'; + export const g = makeTestGroup(ShaderValidationTest); const kCollectiveOps = [ @@ -185,303 +187,240 @@ function generateOp(op) { } } -const kStatementKinds = [ -'if', -'for', -'while', -'switch', -'break-if', -'loop-always-break-op-inside', -'loop-always-return-op-inside', -'loop-always-break-op-continuing', -'loop-always-return-op-continuing', -'loop-always-break-op-after', -'loop-always-return-op-after', -'for-with-cond-always-break-op-inside', -'for-with-cond-always-return-op-inside', -'for-with-cond-always-break-op-after', -'for-with-cond-always-return-op-after', -'for-without-cond-always-break-op-inside', -'for-without-cond-always-return-op-inside', -'for-without-cond-always-break-op-after', -'for-without-cond-always-return-op-after', -'while-always-break-op-inside', -'while-always-return-op-inside', -'while-always-break-op-after', -'while-always-return-op-after']; - - - - - +const kStatementCases = [ +// Basic non-loop cases. +{ + name: 'if', + code: 'if <cond> { <op> }', + verdict: 'sensitive' +}, +{ + name: 'switch', + code: ` + switch u32(<cond>) { + case 0: { + <op> + } + default: { } + }`, + verdict: 'sensitive' +}, +// Loops + +// loop without continuing +// op before the interruption +LoopCase('loop-op-always-break', 'permit'), +LoopCase('loop-op-cond-break', 'sensitive'), +LoopCase('loop-op-always-return', 'permit'), +LoopCase('loop-op-cond-return', 'sensitive'), +LoopCase('loop-unif-break-op-always-continue', 'permit'), +LoopCase('loop-unif-break-op-cond-continue', 'sensitive'), + +// op after the interruption +LoopCase('loop-always-break-op', 'permit'), +LoopCase('loop-cond-break-op', 'sensitive'), +LoopCase('loop-always-return-op', 'permit'), +LoopCase('loop-cond-return-op', 'sensitive'), +LoopCase('loop-unif-break-always-continue-op', 'permit'), +LoopCase('loop-unif-break-cond-continue-op', 'sensitive'), + +// op after the end of the loop +// Without a return, any non-uniformity introduced in the +// loop is resolved by the end of the loop. +LoopCase('loop-always-break-end-op', 'permit'), +LoopCase('loop-unif-break-end-op', 'permit'), +LoopCase('loop-cond-break-end-op', 'permit'), +LoopCase('loop-always-return-end-op', 'permit'), +LoopCase('loop-cond-return-end-op', 'permit'), // the loop can only return +LoopCase('loop-unif-break-always-continue-end-op', 'permit'), +LoopCase('loop-unif-break-cond-continue-end-op', 'permit'), + +// loop with continuing block +// op before the interruption before continuing +LoopCase('loop-op-always-break-continuing', 'permit'), +LoopCase('loop-op-unif-break-continuing', 'permit'), +LoopCase('loop-op-cond-break-continuing', 'sensitive'), +LoopCase('loop-op-always-return-continuing', 'permit'), +LoopCase('loop-op-cond-return-continuing', 'sensitive'), +LoopCase('loop-unif-break-op-always-continue-continuing', 'permit'), +// non re-convergence at the continuing block. +LoopCase('loop-unif-break-op-cond-continue-continuing', 'sensitive'), + +// op in body, interruption in continiuing +// The only permitted interruption in the continuing block +// is cond-break. +LoopCase('loop-op-continuing-cond-break', 'sensitive'), + +// interruption in body, op in continuing +LoopCase('loop-always-break-continuing-op', 'permit'), +LoopCase('loop-cond-break-continuing-op', 'sensitive'), +LoopCase('loop-always-return-continuing-op', 'permit'), +LoopCase('loop-cond-return-continuing-op', 'sensitive'), + +// op and interruption in continuing +LoopCase('loop-continuing-op-cond-break', 'sensitive'), + +// interruption in body, op after end +LoopCase('loop-always-break-continuing-end-op', 'permit'), +LoopCase('loop-cond-break-continuing-end-op', 'permit'), +LoopCase('loop-always-return-continuing-end-op', 'permit'), +LoopCase('loop-cond-return-continuing-end-op', 'permit'), // the looop can only return +LoopCase('loop-unif-break-always-continue-continuing-end-op', 'permit'), +LoopCase('loop-unif-break-cond-continue-continuing-end-op', 'permit'), + +// interruption in continuing, op after end +LoopCase('loop-continuing-cond-break-end-op', 'permit'), +LoopCase('loop-always-break-continuing-cond-break-end-op', 'permit'), +LoopCase('loop-always-return-continuing-cond-break-end-op', 'permit'), + +// Unconditional for +// interruption then op +LoopCase('for-always-break-op', 'permit'), +LoopCase('for-cond-break-op', 'sensitive'), +LoopCase('for-always-return-op', 'permit'), +LoopCase('for-cond-return-op', 'sensitive'), +LoopCase('for-unif-unif-break-always-continue-op', 'permit'), +LoopCase('for-unif-unif-break-cond-continue-op', 'sensitive'), +// op then interruption +LoopCase('for-op-always-break', 'permit'), +LoopCase('for-op-cond-break', 'sensitive'), +LoopCase('for-op-always-return', 'permit'), +LoopCase('for-op-cond-return', 'sensitive'), +LoopCase('for-op-unif-break-always-continue', 'permit'), +LoopCase('for-op-unif-break-cond-continue', 'sensitive'), + +// For with uniform condition +LoopCase('for-unif-op', 'permit'), +// interruption, then op +LoopCase('for-unif-always-break-op', 'permit'), +LoopCase('for-unif-cond-break-op', 'sensitive'), +LoopCase('for-unif-always-return-op', 'permit'), +LoopCase('for-unif-cond-return-op', 'sensitive'), +LoopCase('for-unif-always-continue-op', 'permit'), +LoopCase('for-unif-cond-continue-op', 'sensitive'), +// op, then interruption +LoopCase('for-unif-op-always-break', 'permit'), +LoopCase('for-unif-op-cond-break', 'sensitive'), +LoopCase('for-unif-op-always-return', 'permit'), +LoopCase('for-unif-op-cond-return', 'sensitive'), +LoopCase('for-unif-op-always-continue', 'permit'), +LoopCase('for-unif-op-cond-continue', 'sensitive'), +// interruption, then op after loop +LoopCase('for-unif-end-op', 'permit'), +LoopCase('for-unif-always-break-end-op', 'permit'), +LoopCase('for-unif-cond-break-end-op', 'permit'), +LoopCase('for-unif-always-return-end-op', 'permit'), +LoopCase('for-unif-cond-return-end-op', 'sensitive'), +LoopCase('for-unif-always-continue-end-op', 'permit'), +LoopCase('for-unif-cond-continue-end-op', 'permit'), + +// For with non-uniform condition +LoopCase('for-nonunif-op', 'forbid'), +// interruption, then op +LoopCase('for-nonunif-always-break-op', 'permit'), +LoopCase('for-nonunif-cond-break-op', 'forbid'), +LoopCase('for-nonunif-always-return-op', 'permit'), +LoopCase('for-nonunif-cond-return-op', 'forbid'), +LoopCase('for-nonunif-always-continue-op', 'permit'), +LoopCase('for-nonunif-cond-continue-op', 'forbid'), +// op, then interruption +LoopCase('for-nonunif-op-always-break', 'forbid'), +LoopCase('for-nonunif-op-cond-break', 'forbid'), +LoopCase('for-nonunif-op-always-return', 'forbid'), +LoopCase('for-nonunif-op-cond-return', 'forbid'), +LoopCase('for-nonunif-op-always-continue', 'forbid'), +LoopCase('for-nonunif-op-cond-continue', 'forbid'), +// interruption, then op after loop +LoopCase('for-nonunif-end-op', 'permit'), +LoopCase('for-nonunif-always-break-end-op', 'permit'), +LoopCase('for-nonunif-cond-break-end-op', 'permit'), +LoopCase('for-nonunif-always-return-end-op', 'forbid'), +LoopCase('for-nonunif-cond-return-end-op', 'forbid'), +LoopCase('for-nonunif-always-continue-end-op', 'permit'), +LoopCase('for-nonunif-cond-continue-end-op', 'permit'), + +// While with uniform condition +LoopCase('while-unif-op', 'permit'), +// interruption, then op +LoopCase('while-unif-always-break-op', 'permit'), +LoopCase('while-unif-cond-break-op', 'sensitive'), +LoopCase('while-unif-always-return-op', 'permit'), +LoopCase('while-unif-cond-return-op', 'sensitive'), +LoopCase('while-unif-always-continue-op', 'permit'), +LoopCase('while-unif-cond-continue-op', 'sensitive'), +// op, then interruption +LoopCase('while-unif-op-always-break', 'permit'), +LoopCase('while-unif-op-cond-break', 'sensitive'), +LoopCase('while-unif-op-always-return', 'permit'), +LoopCase('while-unif-op-cond-return', 'sensitive'), +LoopCase('while-unif-op-always-continue', 'permit'), +LoopCase('while-unif-op-cond-continue', 'sensitive'), +// interruption, then op after loop +LoopCase('while-unif-end-op', 'permit'), +LoopCase('while-unif-always-break-end-op', 'permit'), +LoopCase('while-unif-cond-break-end-op', 'permit'), +LoopCase('while-unif-always-return-end-op', 'permit'), +LoopCase('while-unif-cond-return-end-op', 'sensitive'), +LoopCase('while-unif-always-continue-end-op', 'permit'), +LoopCase('while-unif-cond-continue-end-op', 'permit'), + +// While with non-uniform condition +LoopCase('while-nonunif-op', 'forbid'), +// interruption, then op +LoopCase('while-nonunif-always-break-op', 'permit'), +LoopCase('while-nonunif-cond-break-op', 'forbid'), +LoopCase('while-nonunif-always-return-op', 'permit'), +LoopCase('while-nonunif-cond-return-op', 'forbid'), +LoopCase('while-nonunif-always-continue-op', 'permit'), +LoopCase('while-nonunif-cond-continue-op', 'forbid'), +// op, then interruption +LoopCase('while-nonunif-op-always-break', 'forbid'), +LoopCase('while-nonunif-op-cond-break', 'forbid'), +LoopCase('while-nonunif-op-always-return', 'forbid'), +LoopCase('while-nonunif-op-cond-return', 'forbid'), +LoopCase('while-nonunif-op-always-continue', 'forbid'), +LoopCase('while-nonunif-op-cond-continue', 'forbid'), +// interruption, then op after loop +LoopCase('while-nonunif-end-op', 'permit'), +LoopCase('while-nonunif-always-break-end-op', 'permit'), +LoopCase('while-nonunif-cond-break-end-op', 'permit'), +LoopCase('while-nonunif-always-return-end-op', 'forbid'), +LoopCase('while-nonunif-cond-return-end-op', 'forbid'), +LoopCase('while-nonunif-always-continue-end-op', 'permit'), +LoopCase('while-nonunif-cond-continue-end-op', 'permit')]; + + +const kStatementNames = kStatementCases.map((sc) => sc.name); + +// Lookup table by statement name +const kStatementDict = Object.fromEntries(kStatementCases.map((sc) => [sc.name, sc])); function generateConditionalStatement( -statement, +name, condition_name, op_name) { const cond = generateCondition(condition_name); - const uniform_cond = generateCondition('uniform_storage_ro'); const op = generateOp(op_name); - switch (statement) { - case 'if':{ - return { - sensitive: true, - code: ` - if ${cond} { - ${op}; - }` - }; - } - case 'for':{ - return { - sensitive: true, - code: ` - for (; ${cond}; ) { - ${op}; - }` - }; - } - case 'while':{ - return { - sensitive: true, - code: ` - while ${cond} { - ${op}; - }` - }; - } - case 'switch':{ - return { - sensitive: true, - code: ` - switch u32(${cond}) { - case 0: { - ${op}; - } - default: { } - }` - }; - } - case 'break-if':{ - // The initial 'if' prevents the loop from being infinite. Its condition - // is uniform, to ensure the first iteration of the the body executes - // uniformly. The uniformity of the second iteration depends entirely on - // the uniformity of the break-if condition. - return { - sensitive: true, - code: ` - loop { - if ${uniform_cond} { break; } - ${op} - continuing { - break if ${cond}; - } - }` - }; - } - case 'loop-always-break-op-inside':{ - return { - sensitive: false, // The op is unreachable. - code: ` - loop { - break; - if ${cond} { ${op} } - }` - }; - } - case 'loop-always-return-op-inside':{ - return { - sensitive: false, // The op is unreachable. - code: ` - loop { - return; - if ${cond} { ${op} } - }` - }; - } - case 'loop-always-break-op-continuing':{ - return { - sensitive: false, // The op is unreachable. - code: ` - loop { - break; - continuing { - if ${cond} { ${op} } - } - }` - }; - } - case 'loop-always-return-op-continuing':{ - return { - sensitive: false, // The op is unreachable. - code: ` - loop { - return; - continuing { - if ${cond} { ${op} } - } - }` - }; - } - case 'loop-always-break-op-after':{ - return { - sensitive: true, - code: ` - loop { - break; - } - if ${cond} { ${op} }` - }; - } - case 'loop-always-return-op-after':{ - return { - sensitive: false, // The op is unreachable. - code: ` - loop { - return; - } - if ${cond} { ${op} }` - }; - } - case 'for-with-cond-always-break-op-inside':{ - return { - sensitive: false, // The op is unreachable. - code: ` - for ( ;${uniform_cond}; ) { - break; - if ${cond} { ${op} } - }` - }; - } - case 'for-with-cond-always-return-op-inside':{ - return { - sensitive: false, // The op is unreachable. - code: ` - for ( ;${uniform_cond}; ) { - return; - if ${cond} { ${op} } - }` - }; - } - case 'for-with-cond-always-break-op-after':{ - return { - sensitive: true, - code: ` - for ( ;${uniform_cond}; ) { - break; - } - if ${cond} { ${op} }` - }; - } - case 'for-with-cond-always-return-op-after':{ - return { - // Desugars to a loop with a conditional break, - // before reaching the loop. - sensitive: true, - code: ` - for ( ;${uniform_cond}; ) { - return; - } - if ${cond} { ${op} }` - }; - } - case 'for-without-cond-always-break-op-inside':{ - return { - sensitive: false, // The op is unreachable. - code: ` - for ( ; ; ) { - break; - if ${cond} { ${op} } - }` - }; - } - case 'for-without-cond-always-return-op-inside':{ - return { - sensitive: false, // The op is unreachable. - code: ` - for ( ; ; ) { - return; - if ${cond} { ${op} } - }` - }; - } - case 'for-without-cond-always-break-op-after':{ - return { - sensitive: true, - code: ` - for ( ; ; ) { - break; - } - if ${cond} { ${op} }` - }; - } - case 'for-without-cond-always-return-op-after':{ - return { - // Desugars to a loop without a conditional break. - // So the op is unreachable. - sensitive: false, - code: ` - for ( ; ; ) { - return; - } - if ${cond} { ${op} }` - }; - } - case 'while-always-break-op-inside':{ - return { - sensitive: false, // The op is unreachable. - code: ` - while (${uniform_cond}) { - break; - if ${cond} { ${op} } - }` - }; - } - case 'while-always-return-op-inside':{ - return { - sensitive: false, // The op is unreachable. - code: ` - while (${uniform_cond}) { - return; - if ${cond} { ${op} } - }` - }; - } - case 'while-always-break-op-after':{ - return { - sensitive: true, - code: ` - while (${uniform_cond}) { - break; - } - if ${cond} { ${op} }` - }; - } - case 'while-always-return-op-after':{ - return { - // Desugars to a loop with a conditional break, - // before reaching the loop. - sensitive: true, - code: ` - while (${uniform_cond}) { - return; - } - if ${cond} { ${op} }` - }; - } - } + const snippet = kStatementDict[name]; + let code = snippet.code; + code = code. + replace('<op>', op). + replace('<cond>', cond). + replaceAll('<uniform_cond>', generateCondition('uniform_storage_ro')). + replaceAll('<nonuniform_cond>', generateCondition('nonuniform_storage_ro')); + return { name, code, verdict: snippet.verdict }; } g.test('basics'). desc(`Test collective operations in simple uniform or non-uniform control flow.`). params((u) => u. -combine('statement', kStatementKinds). +combine('statement', kStatementNames). beginSubcases(). combineWithParams(kConditions). combineWithParams(kCollectiveOps) @@ -522,11 +461,11 @@ fn((t) => { code += `@builtin(position) p : vec4<f32>`; } code += `) { - let u_let = uniform_buffer.x; - let n_let = rw_buffer[0]; - var u_f = uniform_buffer.z; - var n_f = rw_buffer[1]; - `; + let u_let = uniform_buffer.x; + let n_let = rw_buffer[0]; + var u_f = uniform_buffer.z; + var n_f = rw_buffer[1]; +`; // Simple control statement containing the op. const snippet = generateConditionalStatement(t.params.statement, t.params.cond, t.params.op); @@ -535,7 +474,11 @@ fn((t) => { code += `\n}\n`; t.expectCompileResult( - t.params.expectation || t.params.op.startsWith('control_case') || !snippet.sensitive, + compileShouldSucceed({ + requires_uniformity: !t.params.op.startsWith('control_case'), + condition_is_uniform: t.params.expectation, + verdict: snippet.verdict + }), code ); }); @@ -573,7 +516,7 @@ g.test('basics,subgroups'). desc(`Test subgroup operations in simple uniform or non-uniform control flow.`). params((u) => u. -combine('statement', kStatementKinds). +combine('statement', kStatementNames). beginSubcases(). combineWithParams(kConditions). combine('op', kSubgroupOps). @@ -626,7 +569,11 @@ fn((t) => { code += `\n}\n`; t.expectCompileResult( - t.params.expectation || t.params.op.startsWith('control_case') || !snippet.sensitive, + compileShouldSucceed({ + requires_uniformity: !t.params.op.startsWith('control_case'), + condition_is_uniform: t.params.expectation, + verdict: snippet.verdict + }), code ); });